pacemaker  1.1.24-3850484742
Scalable High-Availability cluster resource manager
utils.c
Go to the documentation of this file.
1 /*
2  * Copyright 2004-2019 the Pacemaker project contributors
3  *
4  * The version control history for this file may have further details.
5  *
6  * This source code is licensed under the GNU Lesser General Public License
7  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8  */
9 
10 #include <crm_internal.h>
11 #include <dlfcn.h>
12 
13 #ifndef _GNU_SOURCE
14 # define _GNU_SOURCE
15 #endif
16 
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <sys/stat.h>
20 #include <sys/utsname.h>
21 
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <limits.h>
27 #include <pwd.h>
28 #include <time.h>
29 #include <libgen.h>
30 #include <signal.h>
31 
32 #include <qb/qbdefs.h>
33 
34 #include <crm/crm.h>
35 #include <crm/services.h>
36 #include <crm/msg_xml.h>
37 #include <crm/cib/internal.h>
38 #include <crm/common/xml.h>
39 #include <crm/common/util.h>
40 #include <crm/common/ipc.h>
41 #include <crm/common/iso8601.h>
42 #include <crm/common/mainloop.h>
43 #include <libxml2/libxml/relaxng.h>
44 
45 #ifndef MAXLINE
46 # define MAXLINE 512
47 #endif
48 
49 #ifdef HAVE_GETOPT_H
50 # include <getopt.h>
51 #endif
52 
53 #ifndef PW_BUFFER_LEN
54 # define PW_BUFFER_LEN 500
55 #endif
56 
57 CRM_TRACE_INIT_DATA(common);
58 
59 gboolean crm_config_error = FALSE;
60 gboolean crm_config_warning = FALSE;
61 char *crm_system_name = NULL;
62 
67 
68 static struct crm_option *crm_long_options = NULL;
69 static const char *crm_app_description = NULL;
70 static char *crm_short_options = NULL;
71 static const char *crm_app_usage = NULL;
72 
73 int
74 crm_exit(int rc)
75 {
77 
78 #if HAVE_LIBXML2
79  crm_trace("cleaning up libxml");
81 #endif
82 
83  crm_trace("exit %d", rc);
84  qb_log_fini();
85 
86  free(crm_short_options);
87  free(crm_system_name);
88 
89  exit(ABS(rc)); /* Always exit with a positive value so that it can be passed to crm_error
90  *
91  * Otherwise the system wraps it around and people
92  * have to jump through hoops figuring out what the
93  * error was
94  */
95  return rc; /* Can never happen, but allows return crm_exit(rc)
96  * where "return rc" was used previously - which
97  * keeps compilers happy.
98  */
99 }
100 
101 gboolean
102 check_time(const char *value)
103 {
104  if (crm_get_msec(value) < 5000) {
105  return FALSE;
106  }
107  return TRUE;
108 }
109 
110 gboolean
111 check_timer(const char *value)
112 {
113  if (crm_get_msec(value) < 0) {
114  return FALSE;
115  }
116  return TRUE;
117 }
118 
119 gboolean
120 check_boolean(const char *value)
121 {
122  int tmp = FALSE;
123 
124  if (crm_str_to_boolean(value, &tmp) != 1) {
125  return FALSE;
126  }
127  return TRUE;
128 }
129 
130 gboolean
131 check_number(const char *value)
132 {
133  errno = 0;
134  if (value == NULL) {
135  return FALSE;
136 
137  } else if (safe_str_eq(value, MINUS_INFINITY_S)) {
138 
139  } else if (safe_str_eq(value, INFINITY_S)) {
140 
141  } else {
142  crm_int_helper(value, NULL);
143  }
144 
145  if (errno != 0) {
146  return FALSE;
147  }
148  return TRUE;
149 }
150 
151 gboolean
152 check_positive_number(const char* value)
153 {
154  if (safe_str_eq(value, INFINITY_S) || (crm_int_helper(value, NULL))) {
155  return TRUE;
156  }
157  return FALSE;
158 }
159 
160 gboolean
161 check_quorum(const char *value)
162 {
163  if (safe_str_eq(value, "stop")) {
164  return TRUE;
165 
166  } else if (safe_str_eq(value, "freeze")) {
167  return TRUE;
168 
169  } else if (safe_str_eq(value, "ignore")) {
170  return TRUE;
171 
172  } else if (safe_str_eq(value, "suicide")) {
173  return TRUE;
174  }
175  return FALSE;
176 }
177 
178 gboolean
179 check_script(const char *value)
180 {
181  struct stat st;
182 
183  if(safe_str_eq(value, "/dev/null")) {
184  return TRUE;
185  }
186 
187  if(stat(value, &st) != 0) {
188  crm_err("Script %s does not exist", value);
189  return FALSE;
190  }
191 
192  if(S_ISREG(st.st_mode) == 0) {
193  crm_err("Script %s is not a regular file", value);
194  return FALSE;
195  }
196 
197  if( (st.st_mode & (S_IXUSR | S_IXGRP )) == 0) {
198  crm_err("Script %s is not executable", value);
199  return FALSE;
200  }
201 
202  return TRUE;
203 }
204 
205 gboolean
206 check_utilization(const char *value)
207 {
208  char *end = NULL;
209  long number = strtol(value, &end, 10);
210 
211  if(end && end[0] != '%') {
212  return FALSE;
213  } else if(number < 0) {
214  return FALSE;
215  }
216 
217  return TRUE;
218 }
219 
220 int
221 char2score(const char *score)
222 {
223  int score_f = 0;
224 
225  if (score == NULL) {
226 
227  } else if (safe_str_eq(score, MINUS_INFINITY_S)) {
228  score_f = -node_score_infinity;
229 
230  } else if (safe_str_eq(score, INFINITY_S)) {
231  score_f = node_score_infinity;
232 
233  } else if (safe_str_eq(score, "+" INFINITY_S)) {
234  score_f = node_score_infinity;
235 
236  } else if (safe_str_eq(score, "red")) {
237  score_f = node_score_red;
238 
239  } else if (safe_str_eq(score, "yellow")) {
240  score_f = node_score_yellow;
241 
242  } else if (safe_str_eq(score, "green")) {
243  score_f = node_score_green;
244 
245  } else {
246  score_f = crm_parse_int(score, NULL);
247  if (score_f > 0 && score_f > node_score_infinity) {
248  score_f = node_score_infinity;
249 
250  } else if (score_f < 0 && score_f < -node_score_infinity) {
251  score_f = -node_score_infinity;
252  }
253  }
254 
255  return score_f;
256 }
257 
258 char *
259 score2char_stack(int score, char *buf, size_t len)
260 {
261  if (score >= node_score_infinity) {
262  strncpy(buf, INFINITY_S, 9);
263  } else if (score <= -node_score_infinity) {
264  strncpy(buf, MINUS_INFINITY_S , 10);
265  } else {
266  return crm_itoa_stack(score, buf, len);
267  }
268 
269  return buf;
270 }
271 
272 char *
273 score2char(int score)
274 {
275  if (score >= node_score_infinity) {
276  return strdup(INFINITY_S);
277 
278  } else if (score <= -node_score_infinity) {
279  return strdup("-" INFINITY_S);
280  }
281  return crm_itoa(score);
282 }
283 
284 const char *
285 cluster_option(GHashTable * options, gboolean(*validate) (const char *),
286  const char *name, const char *old_name, const char *def_value)
287 {
288  const char *value = NULL;
289  char *new_value = NULL;
290 
291  CRM_ASSERT(name != NULL);
292 
293  if (options) {
294  value = g_hash_table_lookup(options, name);
295 
296  if ((value == NULL) && old_name) {
297  value = g_hash_table_lookup(options, old_name);
298  if (value != NULL) {
299  crm_config_warn("Support for legacy name '%s' for cluster option '%s'"
300  " is deprecated and will be removed in a future release",
301  old_name, name);
302 
303  // Inserting copy with current name ensures we only warn once
304  new_value = strdup(value);
305  g_hash_table_insert(options, strdup(name), new_value);
306  value = new_value;
307  }
308  }
309 
310  if (value && validate && (validate(value) == FALSE)) {
311  crm_config_err("Resetting cluster option '%s' to default: value '%s' is invalid",
312  name, value);
313  value = NULL;
314  }
315 
316  if (value) {
317  return value;
318  }
319  }
320 
321  // No value found, use default
322  value = def_value;
323 
324  if (value == NULL) {
325  crm_trace("No value or default provided for cluster option '%s'",
326  name);
327  return NULL;
328  }
329 
330  if (validate) {
331  CRM_CHECK(validate(value) != FALSE,
332  crm_err("Bug: default value for cluster option '%s' is invalid", name);
333  return NULL);
334  }
335 
336  crm_trace("Using default value '%s' for cluster option '%s'",
337  value, name);
338  if (options) {
339  new_value = strdup(value);
340  g_hash_table_insert(options, strdup(name), new_value);
341  value = new_value;
342  }
343  return value;
344 }
345 
346 const char *
347 get_cluster_pref(GHashTable * options, pe_cluster_option * option_list, int len, const char *name)
348 {
349  const char *value = NULL;
350 
351  for (int lpc = 0; lpc < len; lpc++) {
352  if (safe_str_eq(name, option_list[lpc].name)) {
353  value = cluster_option(options,
354  option_list[lpc].is_valid,
355  option_list[lpc].name,
356  option_list[lpc].alt_name,
357  option_list[lpc].default_value);
358  return value;
359  }
360  }
361  CRM_CHECK(FALSE, crm_err("Bug: looking for unknown option '%s'", name));
362  return NULL;
363 }
364 
365 void
366 config_metadata(const char *name, const char *version, const char *desc_short,
367  const char *desc_long, pe_cluster_option * option_list, int len)
368 {
369  int lpc = 0;
370 
371  fprintf(stdout, "<?xml version=\"1.0\"?>"
372  "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
373  "<resource-agent name=\"%s\">\n"
374  " <version>%s</version>\n"
375  " <longdesc lang=\"en\">%s</longdesc>\n"
376  " <shortdesc lang=\"en\">%s</shortdesc>\n"
377  " <parameters>\n", name, version, desc_long, desc_short);
378 
379  for (lpc = 0; lpc < len; lpc++) {
380  if (option_list[lpc].description_long == NULL && option_list[lpc].description_short == NULL) {
381  continue;
382  }
383  fprintf(stdout, " <parameter name=\"%s\" unique=\"0\">\n"
384  " <shortdesc lang=\"en\">%s</shortdesc>\n"
385  " <content type=\"%s\" default=\"%s\"/>\n"
386  " <longdesc lang=\"en\">%s%s%s</longdesc>\n"
387  " </parameter>\n",
388  option_list[lpc].name,
389  option_list[lpc].description_short,
390  option_list[lpc].type,
391  option_list[lpc].default_value,
392  option_list[lpc].description_long ? option_list[lpc].
393  description_long : option_list[lpc].description_short,
394  option_list[lpc].values ? " Allowed values: " : "",
395  option_list[lpc].values ? option_list[lpc].values : "");
396  }
397  fprintf(stdout, " </parameters>\n</resource-agent>\n");
398 }
399 
400 void
401 verify_all_options(GHashTable * options, pe_cluster_option * option_list, int len)
402 {
403  int lpc = 0;
404 
405  for (lpc = 0; lpc < len; lpc++) {
406  cluster_option(options,
407  option_list[lpc].is_valid,
408  option_list[lpc].name,
409  option_list[lpc].alt_name, option_list[lpc].default_value);
410  }
411 }
412 
413 char *
414 generate_hash_key(const char *crm_msg_reference, const char *sys)
415 {
416  char *hash_key = crm_concat(sys ? sys : "none", crm_msg_reference, '_');
417 
418  crm_trace("created hash key: (%s)", hash_key);
419  return hash_key;
420 }
421 
422 
423 int
424 crm_user_lookup(const char *name, uid_t * uid, gid_t * gid)
425 {
426  int rc = pcmk_ok;
427  char *buffer = NULL;
428  struct passwd pwd;
429  struct passwd *pwentry = NULL;
430 
431  buffer = calloc(1, PW_BUFFER_LEN);
432  rc = getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry);
433  if (pwentry) {
434  if (uid) {
435  *uid = pwentry->pw_uid;
436  }
437  if (gid) {
438  *gid = pwentry->pw_gid;
439  }
440  crm_trace("User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
441 
442  } else {
443  rc = rc? -rc : -EINVAL;
444  crm_info("User %s lookup: %s", name, pcmk_strerror(rc));
445  }
446 
447  free(buffer);
448  return rc;
449 }
450 
451 static int
452 crm_version_helper(const char *text, char **end_text)
453 {
454  int atoi_result = -1;
455 
456  CRM_ASSERT(end_text != NULL);
457 
458  errno = 0;
459 
460  if (text != NULL && text[0] != 0) {
461  atoi_result = (int)strtol(text, end_text, 10);
462 
463  if (errno == EINVAL) {
464  crm_err("Conversion of '%s' %c failed", text, text[0]);
465  atoi_result = -1;
466  }
467  }
468  return atoi_result;
469 }
470 
471 /*
472  * version1 < version2 : -1
473  * version1 = version2 : 0
474  * version1 > version2 : 1
475  */
476 int
477 compare_version(const char *version1, const char *version2)
478 {
479  int rc = 0;
480  int lpc = 0;
481  char *ver1_copy = NULL, *ver2_copy = NULL;
482  char *rest1 = NULL, *rest2 = NULL;
483 
484  if (version1 == NULL && version2 == NULL) {
485  return 0;
486  } else if (version1 == NULL) {
487  return -1;
488  } else if (version2 == NULL) {
489  return 1;
490  }
491 
492  ver1_copy = strdup(version1);
493  ver2_copy = strdup(version2);
494  rest1 = ver1_copy;
495  rest2 = ver2_copy;
496 
497  while (1) {
498  int digit1 = 0;
499  int digit2 = 0;
500 
501  lpc++;
502 
503  if (rest1 == rest2) {
504  break;
505  }
506 
507  if (rest1 != NULL) {
508  digit1 = crm_version_helper(rest1, &rest1);
509  }
510 
511  if (rest2 != NULL) {
512  digit2 = crm_version_helper(rest2, &rest2);
513  }
514 
515  if (digit1 < digit2) {
516  rc = -1;
517  break;
518 
519  } else if (digit1 > digit2) {
520  rc = 1;
521  break;
522  }
523 
524  if (rest1 != NULL && rest1[0] == '.') {
525  rest1++;
526  }
527  if (rest1 != NULL && rest1[0] == 0) {
528  rest1 = NULL;
529  }
530 
531  if (rest2 != NULL && rest2[0] == '.') {
532  rest2++;
533  }
534  if (rest2 != NULL && rest2[0] == 0) {
535  rest2 = NULL;
536  }
537  }
538 
539  free(ver1_copy);
540  free(ver2_copy);
541 
542  if (rc == 0) {
543  crm_trace("%s == %s (%d)", version1, version2, lpc);
544  } else if (rc < 0) {
545  crm_trace("%s < %s (%d)", version1, version2, lpc);
546  } else if (rc > 0) {
547  crm_trace("%s > %s (%d)", version1, version2, lpc);
548  }
549 
550  return rc;
551 }
552 
553 gboolean do_stderr = FALSE;
554 
555 #ifndef NUMCHARS
556 # define NUMCHARS "0123456789."
557 #endif
558 
559 #ifndef WHITESPACE
560 # define WHITESPACE " \t\n\r\f"
561 #endif
562 
563 unsigned long long
564 crm_get_interval(const char *input)
565 {
566  unsigned long long msec = 0;
567 
568  if (input == NULL) {
569  return msec;
570 
571  } else if (input[0] != 'P') {
572  long long tmp = crm_get_msec(input);
573 
574  if(tmp > 0) {
575  msec = tmp;
576  }
577 
578  } else {
579  crm_time_t *interval = crm_time_parse_duration(input);
580 
581  msec = 1000 * crm_time_get_seconds(interval);
582  crm_time_free(interval);
583  }
584 
585  return msec;
586 }
587 
588 long long
589 crm_get_msec(const char *input)
590 {
591  const char *cp = input;
592  const char *units;
593  long long multiplier = 1000;
594  long long divisor = 1;
595  long long msec = -1;
596  char *end_text = NULL;
597 
598  /* double dret; */
599 
600  if (input == NULL) {
601  return msec;
602  }
603 
604  cp += strspn(cp, WHITESPACE);
605  units = cp + strspn(cp, NUMCHARS);
606  units += strspn(units, WHITESPACE);
607 
608  if (strchr(NUMCHARS, *cp) == NULL) {
609  return msec;
610  }
611 
612  if (strncasecmp(units, "ms", 2) == 0 || strncasecmp(units, "msec", 4) == 0) {
613  multiplier = 1;
614  divisor = 1;
615  } else if (strncasecmp(units, "us", 2) == 0 || strncasecmp(units, "usec", 4) == 0) {
616  multiplier = 1;
617  divisor = 1000;
618  } else if (strncasecmp(units, "s", 1) == 0 || strncasecmp(units, "sec", 3) == 0) {
619  multiplier = 1000;
620  divisor = 1;
621  } else if (strncasecmp(units, "m", 1) == 0 || strncasecmp(units, "min", 3) == 0) {
622  multiplier = 60 * 1000;
623  divisor = 1;
624  } else if (strncasecmp(units, "h", 1) == 0 || strncasecmp(units, "hr", 2) == 0) {
625  multiplier = 60 * 60 * 1000;
626  divisor = 1;
627  } else if (*units != EOS && *units != '\n' && *units != '\r') {
628  return msec;
629  }
630 
631  msec = crm_int_helper(cp, &end_text);
632  if (msec > LLONG_MAX/multiplier) {
633  /* arithmetics overflow while multiplier/divisor mutually exclusive */
634  return LLONG_MAX;
635  }
636  msec *= multiplier;
637  msec /= divisor;
638  /* dret += 0.5; */
639  /* msec = (long long)dret; */
640  return msec;
641 }
642 
643 extern bool crm_is_daemon;
644 
645 /* coverity[+kill] */
646 void
647 crm_abort(const char *file, const char *function, int line,
648  const char *assert_condition, gboolean do_core, gboolean do_fork)
649 {
650  int rc = 0;
651  int pid = 0;
652  int status = 0;
653 
654  /* Implied by the parent's error logging below */
655  /* crm_write_blackbox(0); */
656 
657  if(crm_is_daemon == FALSE) {
658  /* This is a command line tool - do not fork */
659 
660  /* crm_add_logfile(NULL); * Record it to a file? */
661  crm_enable_stderr(TRUE); /* Make sure stderr is enabled so we can tell the caller */
662  do_fork = FALSE; /* Just crash if needed */
663  }
664 
665  if (do_core == FALSE) {
666  crm_err("%s: Triggered assert at %s:%d : %s", function, file, line, assert_condition);
667  return;
668 
669  } else if (do_fork) {
670  pid = fork();
671 
672  } else {
673  crm_err("%s: Triggered fatal assert at %s:%d : %s", function, file, line, assert_condition);
674  }
675 
676  if (pid == -1) {
677  crm_crit("%s: Cannot create core for non-fatal assert at %s:%d : %s",
678  function, file, line, assert_condition);
679  return;
680 
681  } else if(pid == 0) {
682  /* Child process */
683  abort();
684  return;
685  }
686 
687  /* Parent process */
688  crm_err("%s: Forked child %d to record non-fatal assert at %s:%d : %s",
689  function, pid, file, line, assert_condition);
690  crm_write_blackbox(SIGTRAP, NULL);
691 
692  do {
693  rc = waitpid(pid, &status, 0);
694  if(rc == pid) {
695  return; /* Job done */
696  }
697 
698  } while(errno == EINTR);
699 
700  if (errno == ECHILD) {
701  /* crm_mon does this */
702  crm_trace("Cannot wait on forked child %d - SIGCHLD is probably set to SIG_IGN", pid);
703  return;
704  }
705  crm_perror(LOG_ERR, "Cannot wait on forked child %d", pid);
706 }
707 
708 int
709 crm_pid_active(long pid, const char *daemon)
710 {
711  static int last_asked_pid = 0; /* log spam prevention */
712 #if SUPPORT_PROCFS
713  static int have_proc_pid = 0;
714 #else
715  static int have_proc_pid = -1;
716 #endif
717  int rc = 0;
718 
719  if (have_proc_pid == 0) {
720  /* evaluation of /proc/PID/exe applicability via self-introspection */
721  char proc_path[PATH_MAX], exe_path[PATH_MAX];
722  snprintf(proc_path, sizeof(proc_path), "/proc/%lu/exe",
723  (long unsigned int) getpid());
724  have_proc_pid = 1;
725  if (readlink(proc_path, exe_path, sizeof(exe_path) - 1) < 0) {
726  have_proc_pid = -1;
727  }
728  }
729 
730  if (pid <= 0) {
731  return -1;
732 
733  } else if ((rc = kill(pid, 0)) < 0 && errno == ESRCH) {
734  return 0; /* no such PID detected */
735 
736  } else if (rc < 0 && (daemon == NULL || have_proc_pid == -1)) {
737  if (last_asked_pid != pid) {
738  crm_info("Cannot examine PID %ld: %s", pid, strerror(errno));
739  last_asked_pid = pid;
740  }
741  return -2; /* errno != ESRCH */
742 
743  } else if (rc == 0 && (daemon == NULL || have_proc_pid == -1)) {
744  return 1; /* kill as the only indicator, cannot double check */
745 
746  } else if (daemon != NULL) {
747  /* make sure PID hasn't been reused by another process
748  XXX: might still be just a zombie, which could confuse decisions */
749  bool checked_through_kill = (rc == 0);
750  char proc_path[PATH_MAX], exe_path[PATH_MAX], myexe_path[PATH_MAX];
751  snprintf(proc_path, sizeof(proc_path), "/proc/%ld/exe", pid);
752 
753  rc = readlink(proc_path, exe_path, sizeof(exe_path) - 1);
754  if ((rc < 0) && (errno == EACCES)) {
755  if (last_asked_pid != pid) {
756  crm_info("Could not read from %s: %s", proc_path,
757  strerror(errno));
758  last_asked_pid = pid;
759  }
760  return checked_through_kill ? 1 : -2;
761  } else if (rc < 0) {
762  if (last_asked_pid != pid) {
763  crm_err("Could not read from %s: %s (%d)", proc_path,
764  strerror(errno), errno);
765  last_asked_pid = pid;
766  }
767  return 0; /* most likely errno == ENOENT */
768  }
769  exe_path[rc] = '\0';
770 
771  if (daemon[0] != '/') {
772  rc = snprintf(myexe_path, sizeof(myexe_path), CRM_DAEMON_DIR"/%s",
773  daemon);
774  } else {
775  rc = snprintf(myexe_path, sizeof(myexe_path), "%s", daemon);
776  }
777 
778  if (rc > 0 && rc < sizeof(myexe_path) && !strcmp(exe_path, myexe_path)) {
779  return 1;
780  }
781  }
782 
783  return 0;
784 }
785 
786 #define LOCKSTRLEN 11
787 
788 long
789 crm_read_pidfile(const char *filename)
790 {
791  int fd;
792  struct stat sbuf;
793  long pid = -ENOENT;
794  char buf[LOCKSTRLEN + 1];
795 
796  if ((fd = open(filename, O_RDONLY)) < 0) {
797  goto bail;
798  }
799 
800  if (fstat(fd, &sbuf) >= 0 && sbuf.st_size < LOCKSTRLEN) {
801  sleep(2); /* if someone was about to create one,
802  * give'm a sec to do so
803  */
804  }
805 
806  if (read(fd, buf, sizeof(buf)) < 1) {
807  goto bail;
808  }
809 
810  if (sscanf(buf, "%lu", &pid) > 0) {
811  if (pid <= 0) {
812  pid = -ESRCH;
813  } else {
814  crm_trace("Got pid %lu from %s\n", pid, filename);
815  }
816  }
817 
818  bail:
819  if (fd >= 0) {
820  close(fd);
821  }
822  return pid;
823 }
824 
825 long
826 crm_pidfile_inuse(const char *filename, long mypid, const char *daemon)
827 {
828  long pid = crm_read_pidfile(filename);
829 
830  if (pid < 2) {
831  /* Invalid pid */
832  pid = -ENOENT;
833  unlink(filename);
834 
835  } else if (mypid && pid == mypid) {
836  /* In use by us */
837  pid = pcmk_ok;
838 
839  } else if (crm_pid_active(pid, daemon) == FALSE) {
840  /* Contains a stale value */
841  unlink(filename);
842  pid = -ENOENT;
843 
844  } else if (mypid && pid != mypid) {
845  /* locked by existing process - give up */
846  pid = -EEXIST;
847  }
848 
849  return pid;
850 }
851 
852 static int
853 crm_lock_pidfile(const char *filename, const char *name)
854 {
855  long mypid = 0;
856  int fd = 0, rc = 0;
857  char buf[LOCKSTRLEN + 1];
858 
859  mypid = (unsigned long)getpid();
860 
861  rc = crm_pidfile_inuse(filename, 0, name);
862  if (rc == -ENOENT) {
863  /* exists but the process is not active */
864 
865  } else if (rc != pcmk_ok) {
866  /* locked by existing process - give up */
867  return rc;
868  }
869 
870  if ((fd = open(filename, O_CREAT | O_WRONLY | O_EXCL, 0644)) < 0) {
871  /* Hmmh, why did we fail? Anyway, nothing we can do about it */
872  return -errno;
873  }
874 
875  snprintf(buf, sizeof(buf), "%*lu\n", LOCKSTRLEN - 1, mypid);
876  rc = write(fd, buf, LOCKSTRLEN);
877  close(fd);
878 
879  if (rc != LOCKSTRLEN) {
880  crm_perror(LOG_ERR, "Incomplete write to %s", filename);
881  return -errno;
882  }
883 
884  return crm_pidfile_inuse(filename, mypid, name);
885 }
886 
887 void
888 crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
889 {
890  int rc;
891  long pid;
892  const char *devnull = "/dev/null";
893 
894  if (daemonize == FALSE) {
895  return;
896  }
897 
898  /* Check before we even try... */
899  rc = crm_pidfile_inuse(pidfile, 1, name);
900  if(rc < pcmk_ok && rc != -ENOENT) {
901  pid = crm_read_pidfile(pidfile);
902  crm_err("%s: already running [pid %ld in %s]", name, pid, pidfile);
903  printf("%s: already running [pid %ld in %s]\n", name, pid, pidfile);
904  crm_exit(rc);
905  }
906 
907  pid = fork();
908  if (pid < 0) {
909  fprintf(stderr, "%s: could not start daemon\n", name);
910  crm_perror(LOG_ERR, "fork");
911  crm_exit(EINVAL);
912 
913  } else if (pid > 0) {
914  crm_exit(pcmk_ok);
915  }
916 
917  rc = crm_lock_pidfile(pidfile, name);
918  if(rc < pcmk_ok) {
919  crm_err("Could not lock '%s' for %s: %s (%d)", pidfile, name, pcmk_strerror(rc), rc);
920  printf("Could not lock '%s' for %s: %s (%d)\n", pidfile, name, pcmk_strerror(rc), rc);
921  crm_exit(rc);
922  }
923 
924  umask(S_IWGRP | S_IWOTH | S_IROTH);
925 
926  close(STDIN_FILENO);
927  (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */
928  close(STDOUT_FILENO);
929  (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */
930  close(STDERR_FILENO);
931  (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */
932 }
933 
934 char *
935 crm_meta_name(const char *field)
936 {
937  int lpc = 0;
938  int max = 0;
939  char *crm_name = NULL;
940 
941  CRM_CHECK(field != NULL, return NULL);
942  crm_name = crm_concat(CRM_META, field, '_');
943 
944  /* Massage the names so they can be used as shell variables */
945  max = strlen(crm_name);
946  for (; lpc < max; lpc++) {
947  switch (crm_name[lpc]) {
948  case '-':
949  crm_name[lpc] = '_';
950  break;
951  }
952  }
953  return crm_name;
954 }
955 
956 const char *
957 crm_meta_value(GHashTable * hash, const char *field)
958 {
959  char *key = NULL;
960  const char *value = NULL;
961 
962  key = crm_meta_name(field);
963  if (key) {
964  value = g_hash_table_lookup(hash, key);
965  free(key);
966  }
967 
968  return value;
969 }
970 
971 static struct option *
972 crm_create_long_opts(struct crm_option *long_options)
973 {
974  struct option *long_opts = NULL;
975 
976 #ifdef HAVE_GETOPT_H
977  int index = 0, lpc = 0;
978 
979  /*
980  * A previous, possibly poor, choice of '?' as the short form of --help
981  * means that getopt_long() returns '?' for both --help and for "unknown option"
982  *
983  * This dummy entry allows us to differentiate between the two in crm_get_option()
984  * and exit with the correct error code
985  */
986  long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option));
987  long_opts[index].name = "__dummmy__";
988  long_opts[index].has_arg = 0;
989  long_opts[index].flag = 0;
990  long_opts[index].val = '_';
991  index++;
992 
993  for (lpc = 0; long_options[lpc].name != NULL; lpc++) {
994  if (long_options[lpc].name[0] == '-') {
995  continue;
996  }
997 
998  long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option));
999  /*fprintf(stderr, "Creating %d %s = %c\n", index,
1000  * long_options[lpc].name, long_options[lpc].val); */
1001  long_opts[index].name = long_options[lpc].name;
1002  long_opts[index].has_arg = long_options[lpc].has_arg;
1003  long_opts[index].flag = long_options[lpc].flag;
1004  long_opts[index].val = long_options[lpc].val;
1005  index++;
1006  }
1007 
1008  /* Now create the list terminator */
1009  long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option));
1010  long_opts[index].name = NULL;
1011  long_opts[index].has_arg = 0;
1012  long_opts[index].flag = 0;
1013  long_opts[index].val = 0;
1014 #endif
1015 
1016  return long_opts;
1017 }
1018 
1019 void
1020 crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options,
1021  const char *app_desc)
1022 {
1023  if (short_options) {
1024  crm_short_options = strdup(short_options);
1025 
1026  } else if (long_options) {
1027  int lpc = 0;
1028  int opt_string_len = 0;
1029  char *local_short_options = NULL;
1030 
1031  for (lpc = 0; long_options[lpc].name != NULL; lpc++) {
1032  if (long_options[lpc].val && long_options[lpc].val != '-' && long_options[lpc].val < UCHAR_MAX) {
1033  local_short_options = realloc_safe(local_short_options, opt_string_len + 4);
1034  local_short_options[opt_string_len++] = long_options[lpc].val;
1035  /* getopt(3) says: Two colons mean an option takes an optional arg; */
1036  if (long_options[lpc].has_arg == optional_argument) {
1037  local_short_options[opt_string_len++] = ':';
1038  }
1039  if (long_options[lpc].has_arg >= required_argument) {
1040  local_short_options[opt_string_len++] = ':';
1041  }
1042  local_short_options[opt_string_len] = 0;
1043  }
1044  }
1045  crm_short_options = local_short_options;
1046  crm_trace("Generated short option string: '%s'", local_short_options);
1047  }
1048 
1049  if (long_options) {
1050  crm_long_options = long_options;
1051  }
1052  if (app_desc) {
1053  crm_app_description = app_desc;
1054  }
1055  if (app_usage) {
1056  crm_app_usage = app_usage;
1057  }
1058 }
1059 
1060 int
1061 crm_get_option(int argc, char **argv, int *index)
1062 {
1063  return crm_get_option_long(argc, argv, index, NULL);
1064 }
1065 
1066 int
1067 crm_get_option_long(int argc, char **argv, int *index, const char **longname)
1068 {
1069 #ifdef HAVE_GETOPT_H
1070  static struct option *long_opts = NULL;
1071 
1072  if (long_opts == NULL && crm_long_options) {
1073  long_opts = crm_create_long_opts(crm_long_options);
1074  }
1075 
1076  *index = 0;
1077  if (long_opts) {
1078  int flag = getopt_long(argc, argv, crm_short_options, long_opts, index);
1079 
1080  switch (flag) {
1081  case 0:
1082  if (long_opts[*index].val) {
1083  return long_opts[*index].val;
1084  } else if (longname) {
1085  *longname = long_opts[*index].name;
1086  } else {
1087  crm_notice("Unhandled option --%s", long_opts[*index].name);
1088  return flag;
1089  }
1090  case -1: /* End of option processing */
1091  break;
1092  case ':':
1093  crm_trace("Missing argument");
1094  crm_help('?', 1);
1095  break;
1096  case '?':
1097  crm_help('?', *index ? 0 : 1);
1098  break;
1099  }
1100  return flag;
1101  }
1102 #endif
1103 
1104  if (crm_short_options) {
1105  return getopt(argc, argv, crm_short_options);
1106  }
1107 
1108  return -1;
1109 }
1110 
1111 int
1112 crm_help(char cmd, int exit_code)
1113 {
1114  int i = 0;
1115  FILE *stream = (exit_code ? stderr : stdout);
1116 
1117  if (cmd == 'v' || cmd == '$') {
1118  fprintf(stream, "Pacemaker %s\n", PACEMAKER_VERSION);
1119  fprintf(stream, "Written by Andrew Beekhof\n");
1120  goto out;
1121  }
1122 
1123  if (cmd == '!') {
1124  fprintf(stream, "Pacemaker %s (Build: %s): %s\n", PACEMAKER_VERSION, BUILD_VERSION, CRM_FEATURES);
1125  goto out;
1126  }
1127 
1128  fprintf(stream, "%s - %s\n", crm_system_name, crm_app_description);
1129 
1130  if (crm_app_usage) {
1131  fprintf(stream, "Usage: %s %s\n", crm_system_name, crm_app_usage);
1132  }
1133 
1134  if (crm_long_options) {
1135  fprintf(stream, "Options:\n");
1136  for (i = 0; crm_long_options[i].name != NULL; i++) {
1137  if (crm_long_options[i].flags & pcmk_option_hidden) {
1138 
1139  } else if (crm_long_options[i].flags & pcmk_option_paragraph) {
1140  fprintf(stream, "%s\n\n", crm_long_options[i].desc);
1141 
1142  } else if (crm_long_options[i].flags & pcmk_option_example) {
1143  fprintf(stream, "\t#%s\n\n", crm_long_options[i].desc);
1144 
1145  } else if (crm_long_options[i].val == '-' && crm_long_options[i].desc) {
1146  fprintf(stream, "%s\n", crm_long_options[i].desc);
1147 
1148  } else {
1149  /* is val printable as char ? */
1150  if (crm_long_options[i].val && crm_long_options[i].val <= UCHAR_MAX) {
1151  fprintf(stream, " -%c,", crm_long_options[i].val);
1152  } else {
1153  fputs(" ", stream);
1154  }
1155  fprintf(stream, " --%s%s\t%s\n", crm_long_options[i].name,
1156  crm_long_options[i].has_arg == optional_argument ? "[=value]" :
1157  crm_long_options[i].has_arg == required_argument ? "=value" : "",
1158  crm_long_options[i].desc ? crm_long_options[i].desc : "");
1159  }
1160  }
1161 
1162  } else if (crm_short_options) {
1163  fprintf(stream, "Usage: %s - %s\n", crm_system_name, crm_app_description);
1164  for (i = 0; crm_short_options[i] != 0; i++) {
1165  int has_arg = no_argument /* 0 */;
1166 
1167  if (crm_short_options[i + 1] == ':') {
1168  if (crm_short_options[i + 2] == ':')
1169  has_arg = optional_argument /* 2 */;
1170  else
1171  has_arg = required_argument /* 1 */;
1172  }
1173 
1174  fprintf(stream, " -%c %s\n", crm_short_options[i],
1175  has_arg == optional_argument ? "[value]" :
1176  has_arg == required_argument ? "{value}" : "");
1177  i += has_arg;
1178  }
1179  }
1180 
1181  fprintf(stream, "\nReport bugs to %s\n", PACKAGE_BUGREPORT);
1182 
1183  out:
1184  return crm_exit(exit_code);
1185 }
1186 
1187 void cib_ipc_servers_init(qb_ipcs_service_t **ipcs_ro,
1188  qb_ipcs_service_t **ipcs_rw,
1189  qb_ipcs_service_t **ipcs_shm,
1190  struct qb_ipcs_service_handlers *ro_cb,
1191  struct qb_ipcs_service_handlers *rw_cb)
1192 {
1193  *ipcs_ro = mainloop_add_ipc_server(cib_channel_ro, QB_IPC_NATIVE, ro_cb);
1194  *ipcs_rw = mainloop_add_ipc_server(cib_channel_rw, QB_IPC_NATIVE, rw_cb);
1195  *ipcs_shm = mainloop_add_ipc_server(cib_channel_shm, QB_IPC_SHM, rw_cb);
1196 
1197  if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
1198  crm_err("Failed to create cib servers: exiting and inhibiting respawn.");
1199  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1201  }
1202 }
1203 
1204 void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro,
1205  qb_ipcs_service_t *ipcs_rw,
1206  qb_ipcs_service_t *ipcs_shm)
1207 {
1208  qb_ipcs_destroy(ipcs_ro);
1209  qb_ipcs_destroy(ipcs_rw);
1210  qb_ipcs_destroy(ipcs_shm);
1211 }
1212 
1213 qb_ipcs_service_t *
1214 crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb)
1215 {
1216  return mainloop_add_ipc_server(CRM_SYSTEM_CRMD, QB_IPC_NATIVE, cb);
1217 }
1218 
1219 void
1220 attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
1221 {
1222  *ipcs = mainloop_add_ipc_server(T_ATTRD, QB_IPC_NATIVE, cb);
1223 
1224  if (*ipcs == NULL) {
1225  crm_err("Failed to create attrd servers: exiting and inhibiting respawn.");
1226  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1228  }
1229 }
1230 
1231 void
1232 stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
1233 {
1234  *ipcs = mainloop_add_ipc_server_with_prio("stonith-ng", QB_IPC_NATIVE, cb,
1235  QB_LOOP_HIGH);
1236 
1237  if (*ipcs == NULL) {
1238  crm_err("Failed to create stonith-ng servers: exiting and inhibiting respawn.");
1239  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1241  }
1242 }
1243 
1244 void *
1245 find_library_function(void **handle, const char *lib, const char *fn, gboolean fatal)
1246 {
1247  char *error;
1248  void *a_function;
1249 
1250  if (*handle == NULL) {
1251  *handle = dlopen(lib, RTLD_LAZY);
1252  }
1253 
1254  if (!(*handle)) {
1255  crm_err("%sCould not open %s: %s", fatal ? "Fatal: " : "", lib, dlerror());
1256  if (fatal) {
1258  }
1259  return NULL;
1260  }
1261 
1262  a_function = dlsym(*handle, fn);
1263  if (a_function == NULL) {
1264  error = dlerror();
1265  crm_err("%sCould not find %s in %s: %s", fatal ? "Fatal: " : "", fn, lib, error);
1266  if (fatal) {
1268  }
1269  }
1270 
1271  return a_function;
1272 }
1273 
1274 #ifdef HAVE_UUID_UUID_H
1275 # include <uuid/uuid.h>
1276 #endif
1277 
1278 char *
1280 {
1281  unsigned char uuid[16];
1282  char *buffer = malloc(37); /* Including NUL byte */
1283 
1284  uuid_generate(uuid);
1285  uuid_unparse(uuid, buffer);
1286  return buffer;
1287 }
1288 
1296 bool
1297 crm_is_daemon_name(const char *name)
1298 {
1299  return (name &&
1300  (!strcmp(name, CRM_SYSTEM_CRMD)
1301  || !strcmp(name, CRM_SYSTEM_STONITHD)
1302  || !strcmp(name, T_ATTRD)
1303  || !strcmp(name, CRM_SYSTEM_CIB)
1304  || !strcmp(name, CRM_SYSTEM_MCP)
1305  || !strcmp(name, CRM_SYSTEM_DC)
1306  || !strcmp(name, CRM_SYSTEM_TENGINE)
1307  || !strcmp(name, CRM_SYSTEM_LRMD)));
1308 }
1309 
1310 #include <md5.h>
1311 
1312 char *
1313 crm_md5sum(const char *buffer)
1314 {
1315  int lpc = 0, len = 0;
1316  char *digest = NULL;
1317  unsigned char raw_digest[MD5_DIGEST_SIZE];
1318 
1319  if (buffer == NULL) {
1320  buffer = "";
1321  }
1322  len = strlen(buffer);
1323 
1324  crm_trace("Beginning digest of %d bytes", len);
1325  digest = malloc(2 * MD5_DIGEST_SIZE + 1);
1326  if(digest) {
1327  md5_buffer(buffer, len, raw_digest);
1328  for (lpc = 0; lpc < MD5_DIGEST_SIZE; lpc++) {
1329  sprintf(digest + (2 * lpc), "%02x", raw_digest[lpc]);
1330  }
1331  digest[(2 * MD5_DIGEST_SIZE)] = 0;
1332  crm_trace("Digest %s.", digest);
1333 
1334  } else {
1335  crm_err("Could not create digest");
1336  }
1337  return digest;
1338 }
1339 
1340 #ifdef HAVE_GNUTLS_GNUTLS_H
1341 void
1342 crm_gnutls_global_init(void)
1343 {
1344  signal(SIGPIPE, SIG_IGN);
1345  gnutls_global_init();
1346 }
1347 #endif
Services API.
#define T_ATTRD
Definition: msg_xml.h:50
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:190
void * find_library_function(void **handle, const char *lib, const char *fn, gboolean fatal)
Definition: utils.c:1245
void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len)
Definition: utils.c:401
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
Definition: logging.c:435
A dumping ground.
long long crm_get_msec(const char *input)
Definition: utils.c:589
int crm_get_option_long(int argc, char **argv, int *index, const char **longname)
Definition: utils.c:1067
#define crm_notice(fmt, args...)
Definition: logging.h:276
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
Definition: utils.c:424
gboolean do_stderr
Definition: utils.c:553
void crm_enable_stderr(int enable)
Definition: logging.c:921
#define crm_crit(fmt, args...)
Definition: logging.h:273
gboolean check_utilization(const char *value)
Definition: utils.c:206
#define INFINITY
Definition: crm.h:73
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:957
void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro, qb_ipcs_service_t *ipcs_rw, qb_ipcs_service_t *ipcs_shm)
Definition: utils.c:1204
void attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: utils.c:1220
struct crm_time_s crm_time_t
Definition: iso8601.h:37
const char * pcmk_strerror(int rc)
Definition: logging.c:1017
qb_ipcs_service_t * mainloop_add_ipc_server_with_prio(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks, enum qb_loop_priority prio)
Start server-side API end-point, hooked into the internal event loop.
Definition: mainloop.c:655
int node_score_infinity
Definition: utils.c:66
gboolean check_time(const char *value)
Definition: utils.c:102
#define crm_config_err(fmt...)
Definition: crm_internal.h:225
void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
Definition: utils.c:888
void crm_xml_cleanup(void)
Definition: xml.c:4304
#define pcmk_ok
Definition: error.h:45
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:81
void cib_ipc_servers_init(qb_ipcs_service_t **ipcs_ro, qb_ipcs_service_t **ipcs_rw, qb_ipcs_service_t **ipcs_shm, struct qb_ipcs_service_handlers *ro_cb, struct qb_ipcs_service_handlers *rw_cb)
Definition: utils.c:1187
char * crm_md5sum(const char *buffer)
Definition: utils.c:1313
bool crm_is_daemon_name(const char *name)
Check whether a string represents a cluster daemon name.
Definition: utils.c:1297
gboolean crm_config_warning
Definition: utils.c:60
int crm_help(char cmd, int exit_code)
Definition: utils.c:1112
void mainloop_cleanup(void)
Definition: mainloop.c:411
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:157
int node_score_red
Definition: utils.c:63
crm_time_t * crm_time_parse_duration(const char *duration_str)
Definition: iso8601.c:835
#define MINUS_INFINITY_S
Definition: crm.h:71
void crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options, const char *app_desc)
Definition: utils.c:1020
uint32_t pid
Definition: internal.h:77
const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name)
Definition: utils.c:347
char * crm_system_name
Definition: utils.c:61
#define cib_channel_rw
Definition: internal.h:71
char * strerror(int errnum)
#define PACEMAKER_VERSION
Definition: config.h:648
Wrappers for and extensions to glib mainloop.
gboolean check_positive_number(const char *value)
Definition: utils.c:152
char version[256]
Definition: plugin.c:84
void config_metadata(const char *name, const char *version, const char *desc_short, const char *desc_long, pe_cluster_option *option_list, int len)
Definition: utils.c:366
long crm_read_pidfile(const char *filename)
Definition: utils.c:789
#define CRM_SYSTEM_DC
Definition: crm.h:76
#define CRM_SYSTEM_MCP
Definition: crm.h:85
void stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: utils.c:1232
char * crm_meta_name(const char *field)
Definition: utils.c:935
void * md5_buffer(const char *buffer, size_t len, void *resblock)
Definition: md5.c:210
gboolean check_quorum(const char *value)
Definition: utils.c:161
#define PW_BUFFER_LEN
Definition: utils.c:54
#define crm_warn(fmt, args...)
Definition: logging.h:275
int crm_pid_active(long pid, const char *daemon)
Definition: utils.c:709
int daemon(int nochdir, int noclose)
char * generate_hash_key(const char *crm_msg_reference, const char *sys)
Definition: utils.c:414
bool crm_is_daemon
Definition: logging.c:51
Utility functions.
#define CRM_DAEMON_DIR
Definition: config.h:41
char * score2char(int score)
Definition: utils.c:273
#define BUILD_VERSION
Definition: config.h:23
#define LOCKSTRLEN
Definition: utils.c:786
#define pcmk_option_example
Definition: crm_internal.h:72
unsigned long long crm_get_interval(const char *input)
Definition: utils.c:564
#define INFINITY_S
Definition: crm.h:70
#define crm_trace(fmt, args...)
Definition: logging.h:280
const char * cluster_option(GHashTable *options, gboolean(*validate)(const char *), const char *name, const char *old_name, const char *def_value)
Definition: utils.c:285
#define pcmk_option_paragraph
Definition: crm_internal.h:71
#define NUMCHARS
Definition: utils.c:556
int node_score_yellow
Definition: utils.c:65
Wrappers for and extensions to libxml2.
ISO_8601 Date handling.
int crm_exit(int rc)
Definition: utils.c:74
char * crm_generate_uuid(void)
Definition: utils.c:1279
#define EOS
Definition: crm.h:28
char * crm_itoa_stack(int an_int, char *buf, size_t len)
Definition: strings.c:51
int * flag
Definition: crm_internal.h:84
int node_score_green
Definition: utils.c:64
CRM_TRACE_INIT_DATA(common)
#define WHITESPACE
Definition: utils.c:560
#define cib_channel_shm
Definition: internal.h:72
#define CRM_SYSTEM_CRMD
Definition: crm.h:80
long long int crm_time_get_seconds(crm_time_t *dt)
Definition: iso8601.c:270
#define DAEMON_RESPAWN_STOP
Definition: crm.h:55
int compare_version(const char *version1, const char *version2)
Definition: utils.c:477
gboolean check_script(const char *value)
Definition: utils.c:179
#define crm_config_warn(fmt...)
Definition: crm_internal.h:226
#define CRM_SYSTEM_STONITHD
Definition: crm.h:84
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:208
void crm_abort(const char *file, const char *function, int line, const char *assert_condition, gboolean do_core, gboolean do_fork)
Definition: utils.c:647
#define CRM_SYSTEM_CIB
Definition: crm.h:79
#define CRM_SYSTEM_TENGINE
Definition: crm.h:83
gboolean check_timer(const char *value)
Definition: utils.c:111
long crm_pidfile_inuse(const char *filename, long mypid, const char *daemon)
Definition: utils.c:826
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:252
#define CRM_META
Definition: crm.h:43
int char2score(const char *score)
Definition: utils.c:221
#define crm_err(fmt, args...)
Definition: logging.h:274
gboolean check_number(const char *value)
Definition: utils.c:131
#define CRM_SYSTEM_LRMD
Definition: crm.h:81
#define CRM_ASSERT(expr)
Definition: error.h:20
#define pcmk_option_hidden
Definition: crm_internal.h:70
int crm_get_option(int argc, char **argv, int *index)
Definition: utils.c:1061
#define MD5_DIGEST_SIZE
Definition: md5.h:26
Wrappers for and extensions to libqb IPC.
#define PACKAGE_BUGREPORT
Definition: config.h:654
gboolean crm_config_error
Definition: utils.c:59
char * crm_concat(const char *prefix, const char *suffix, char join)
Definition: strings.c:33
char * crm_itoa(int an_int)
Definition: strings.c:61
#define safe_str_eq(a, b)
Definition: util.h:74
qb_ipcs_service_t * mainloop_add_ipc_server(const char *name, enum qb_ipc_type type, struct qb_ipcs_service_handlers *callbacks)
Definition: mainloop.c:648
#define CRM_FEATURES
Definition: config.h:53
gboolean check_boolean(const char *value)
Definition: utils.c:120
#define crm_info(fmt, args...)
Definition: logging.h:277
#define cib_channel_ro
Definition: internal.h:70
char * score2char_stack(int score, char *buf, size_t len)
Definition: utils.c:259
uint64_t flags
Definition: remote.c:156
qb_ipcs_service_t * crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb)
Definition: utils.c:1214
const char * name
Definition: crm_internal.h:77
enum crm_ais_msg_types type
Definition: internal.h:79
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:116