pacemaker  2.0.3-4b1f869f0f
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 
66 
67 static struct crm_option *crm_long_options = NULL;
68 static const char *crm_app_description = NULL;
69 static char *crm_short_options = NULL;
70 static const char *crm_app_usage = NULL;
71 
72 gboolean
73 check_time(const char *value)
74 {
75  if (crm_get_msec(value) < 5000) {
76  return FALSE;
77  }
78  return TRUE;
79 }
80 
81 gboolean
82 check_timer(const char *value)
83 {
84  if (crm_get_msec(value) < 0) {
85  return FALSE;
86  }
87  return TRUE;
88 }
89 
90 gboolean
91 check_boolean(const char *value)
92 {
93  int tmp = FALSE;
94 
95  if (crm_str_to_boolean(value, &tmp) != 1) {
96  return FALSE;
97  }
98  return TRUE;
99 }
100 
101 gboolean
102 check_number(const char *value)
103 {
104  errno = 0;
105  if (value == NULL) {
106  return FALSE;
107 
108  } else if (safe_str_eq(value, CRM_MINUS_INFINITY_S)) {
109 
110  } else if (safe_str_eq(value, CRM_INFINITY_S)) {
111 
112  } else {
113  crm_int_helper(value, NULL);
114  }
115 
116  if (errno != 0) {
117  return FALSE;
118  }
119  return TRUE;
120 }
121 
122 gboolean
123 check_positive_number(const char* value)
124 {
125  if (safe_str_eq(value, CRM_INFINITY_S) || (crm_int_helper(value, NULL))) {
126  return TRUE;
127  }
128  return FALSE;
129 }
130 
131 gboolean
132 check_quorum(const char *value)
133 {
134  if (safe_str_eq(value, "stop")) {
135  return TRUE;
136 
137  } else if (safe_str_eq(value, "freeze")) {
138  return TRUE;
139 
140  } else if (safe_str_eq(value, "ignore")) {
141  return TRUE;
142 
143  } else if (safe_str_eq(value, "demote")) {
144  return TRUE;
145 
146  } else if (safe_str_eq(value, "suicide")) {
147  return TRUE;
148  }
149  return FALSE;
150 }
151 
152 gboolean
153 check_script(const char *value)
154 {
155  struct stat st;
156 
157  if(safe_str_eq(value, "/dev/null")) {
158  return TRUE;
159  }
160 
161  if(stat(value, &st) != 0) {
162  crm_err("Script %s does not exist", value);
163  return FALSE;
164  }
165 
166  if(S_ISREG(st.st_mode) == 0) {
167  crm_err("Script %s is not a regular file", value);
168  return FALSE;
169  }
170 
171  if( (st.st_mode & (S_IXUSR | S_IXGRP )) == 0) {
172  crm_err("Script %s is not executable", value);
173  return FALSE;
174  }
175 
176  return TRUE;
177 }
178 
179 gboolean
180 check_utilization(const char *value)
181 {
182  char *end = NULL;
183  long number = strtol(value, &end, 10);
184 
185  if(end && end[0] != '%') {
186  return FALSE;
187  } else if(number < 0) {
188  return FALSE;
189  }
190 
191  return TRUE;
192 }
193 
194 void
196 {
197  free(crm_short_options);
198  crm_short_options = NULL;
199 }
200 
201 int
202 char2score(const char *score)
203 {
204  int score_f = 0;
205 
206  if (score == NULL) {
207 
208  } else if (safe_str_eq(score, CRM_MINUS_INFINITY_S)) {
209  score_f = -CRM_SCORE_INFINITY;
210 
211  } else if (safe_str_eq(score, CRM_INFINITY_S)) {
212  score_f = CRM_SCORE_INFINITY;
213 
214  } else if (safe_str_eq(score, CRM_PLUS_INFINITY_S)) {
215  score_f = CRM_SCORE_INFINITY;
216 
217  } else if (safe_str_eq(score, "red")) {
218  score_f = node_score_red;
219 
220  } else if (safe_str_eq(score, "yellow")) {
221  score_f = node_score_yellow;
222 
223  } else if (safe_str_eq(score, "green")) {
224  score_f = node_score_green;
225 
226  } else {
227  score_f = crm_parse_int(score, NULL);
228  if (score_f > 0 && score_f > CRM_SCORE_INFINITY) {
229  score_f = CRM_SCORE_INFINITY;
230 
231  } else if (score_f < 0 && score_f < -CRM_SCORE_INFINITY) {
232  score_f = -CRM_SCORE_INFINITY;
233  }
234  }
235 
236  return score_f;
237 }
238 
239 char *
240 score2char_stack(int score, char *buf, size_t len)
241 {
242  if (score >= CRM_SCORE_INFINITY) {
243  strncpy(buf, CRM_INFINITY_S, 9);
244  } else if (score <= -CRM_SCORE_INFINITY) {
245  strncpy(buf, CRM_MINUS_INFINITY_S , 10);
246  } else {
247  return crm_itoa_stack(score, buf, len);
248  }
249 
250  return buf;
251 }
252 
253 char *
254 score2char(int score)
255 {
256  if (score >= CRM_SCORE_INFINITY) {
257  return strdup(CRM_INFINITY_S);
258 
259  } else if (score <= -CRM_SCORE_INFINITY) {
260  return strdup(CRM_MINUS_INFINITY_S);
261  }
262  return crm_itoa(score);
263 }
264 
265 const char *
266 cluster_option(GHashTable * options, gboolean(*validate) (const char *),
267  const char *name, const char *old_name, const char *def_value)
268 {
269  const char *value = NULL;
270  char *new_value = NULL;
271 
272  CRM_ASSERT(name != NULL);
273 
274  if (options) {
275  value = g_hash_table_lookup(options, name);
276 
277  if ((value == NULL) && old_name) {
278  value = g_hash_table_lookup(options, old_name);
279  if (value != NULL) {
280  crm_config_warn("Support for legacy name '%s' for cluster option '%s'"
281  " is deprecated and will be removed in a future release",
282  old_name, name);
283 
284  // Inserting copy with current name ensures we only warn once
285  new_value = strdup(value);
286  g_hash_table_insert(options, strdup(name), new_value);
287  value = new_value;
288  }
289  }
290 
291  if (value && validate && (validate(value) == FALSE)) {
292  crm_config_err("Resetting cluster option '%s' to default: value '%s' is invalid",
293  name, value);
294  value = NULL;
295  }
296 
297  if (value) {
298  return value;
299  }
300  }
301 
302  // No value found, use default
303  value = def_value;
304 
305  if (value == NULL) {
306  crm_trace("No value or default provided for cluster option '%s'",
307  name);
308  return NULL;
309  }
310 
311  if (validate) {
312  CRM_CHECK(validate(value) != FALSE,
313  crm_err("Bug: default value for cluster option '%s' is invalid", name);
314  return NULL);
315  }
316 
317  crm_trace("Using default value '%s' for cluster option '%s'",
318  value, name);
319  if (options) {
320  new_value = strdup(value);
321  g_hash_table_insert(options, strdup(name), new_value);
322  value = new_value;
323  }
324  return value;
325 }
326 
327 const char *
328 get_cluster_pref(GHashTable * options, pe_cluster_option * option_list, int len, const char *name)
329 {
330  const char *value = NULL;
331 
332  for (int lpc = 0; lpc < len; lpc++) {
333  if (safe_str_eq(name, option_list[lpc].name)) {
334  value = cluster_option(options,
335  option_list[lpc].is_valid,
336  option_list[lpc].name,
337  option_list[lpc].alt_name,
338  option_list[lpc].default_value);
339  return value;
340  }
341  }
342  CRM_CHECK(FALSE, crm_err("Bug: looking for unknown option '%s'", name));
343  return NULL;
344 }
345 
346 void
347 config_metadata(const char *name, const char *version, const char *desc_short,
348  const char *desc_long, pe_cluster_option * option_list, int len)
349 {
350  int lpc = 0;
351 
352  fprintf(stdout, "<?xml version=\"1.0\"?>"
353  "<!DOCTYPE resource-agent SYSTEM \"ra-api-1.dtd\">\n"
354  "<resource-agent name=\"%s\">\n"
355  " <version>%s</version>\n"
356  " <longdesc lang=\"en\">%s</longdesc>\n"
357  " <shortdesc lang=\"en\">%s</shortdesc>\n"
358  " <parameters>\n", name, version, desc_long, desc_short);
359 
360  for (lpc = 0; lpc < len; lpc++) {
361  if (option_list[lpc].description_long == NULL && option_list[lpc].description_short == NULL) {
362  continue;
363  }
364  fprintf(stdout, " <parameter name=\"%s\" unique=\"0\">\n"
365  " <shortdesc lang=\"en\">%s</shortdesc>\n"
366  " <content type=\"%s\" default=\"%s\"/>\n"
367  " <longdesc lang=\"en\">%s%s%s</longdesc>\n"
368  " </parameter>\n",
369  option_list[lpc].name,
370  option_list[lpc].description_short,
371  option_list[lpc].type,
372  option_list[lpc].default_value,
373  option_list[lpc].description_long ? option_list[lpc].
374  description_long : option_list[lpc].description_short,
375  option_list[lpc].values ? " Allowed values: " : "",
376  option_list[lpc].values ? option_list[lpc].values : "");
377  }
378  fprintf(stdout, " </parameters>\n</resource-agent>\n");
379 }
380 
381 void
382 verify_all_options(GHashTable * options, pe_cluster_option * option_list, int len)
383 {
384  int lpc = 0;
385 
386  for (lpc = 0; lpc < len; lpc++) {
387  cluster_option(options,
388  option_list[lpc].is_valid,
389  option_list[lpc].name,
390  option_list[lpc].alt_name, option_list[lpc].default_value);
391  }
392 }
393 
394 char *
395 generate_hash_key(const char *crm_msg_reference, const char *sys)
396 {
397  char *hash_key = crm_concat(sys ? sys : "none", crm_msg_reference, '_');
398 
399  crm_trace("created hash key: (%s)", hash_key);
400  return hash_key;
401 }
402 
403 
404 int
405 crm_user_lookup(const char *name, uid_t * uid, gid_t * gid)
406 {
407  int rc = pcmk_ok;
408  char *buffer = NULL;
409  struct passwd pwd;
410  struct passwd *pwentry = NULL;
411 
412  buffer = calloc(1, PW_BUFFER_LEN);
413  rc = getpwnam_r(name, &pwd, buffer, PW_BUFFER_LEN, &pwentry);
414  if (pwentry) {
415  if (uid) {
416  *uid = pwentry->pw_uid;
417  }
418  if (gid) {
419  *gid = pwentry->pw_gid;
420  }
421  crm_trace("User %s has uid=%d gid=%d", name, pwentry->pw_uid, pwentry->pw_gid);
422 
423  } else {
424  rc = rc? -rc : -EINVAL;
425  crm_info("User %s lookup: %s", name, pcmk_strerror(rc));
426  }
427 
428  free(buffer);
429  return rc;
430 }
431 
432 static int
433 crm_version_helper(const char *text, const char **end_text)
434 {
435  int atoi_result = -1;
436 
437  CRM_ASSERT(end_text != NULL);
438 
439  errno = 0;
440 
441  if (text != NULL && text[0] != 0) {
442  /* seemingly sacrificing const-correctness -- because while strtol
443  doesn't modify the input, it doesn't want to artificially taint the
444  "end_text" pointer-to-pointer-to-first-char-in-string with constness
445  in case the input wasn't actually constant -- by semantic definition
446  not a single character will get modified so it shall be perfectly
447  safe to make compiler happy with dropping "const" qualifier here */
448  atoi_result = (int) strtol(text, (char **) end_text, 10);
449 
450  if (errno == EINVAL) {
451  crm_err("Conversion of '%s' %c failed", text, text[0]);
452  atoi_result = -1;
453  }
454  }
455  return atoi_result;
456 }
457 
458 /*
459  * version1 < version2 : -1
460  * version1 = version2 : 0
461  * version1 > version2 : 1
462  */
463 int
464 compare_version(const char *version1, const char *version2)
465 {
466  int rc = 0;
467  int lpc = 0;
468  const char *ver1_iter, *ver2_iter;
469 
470  if (version1 == NULL && version2 == NULL) {
471  return 0;
472  } else if (version1 == NULL) {
473  return -1;
474  } else if (version2 == NULL) {
475  return 1;
476  }
477 
478  ver1_iter = version1;
479  ver2_iter = version2;
480 
481  while (1) {
482  int digit1 = 0;
483  int digit2 = 0;
484 
485  lpc++;
486 
487  if (ver1_iter == ver2_iter) {
488  break;
489  }
490 
491  if (ver1_iter != NULL) {
492  digit1 = crm_version_helper(ver1_iter, &ver1_iter);
493  }
494 
495  if (ver2_iter != NULL) {
496  digit2 = crm_version_helper(ver2_iter, &ver2_iter);
497  }
498 
499  if (digit1 < digit2) {
500  rc = -1;
501  break;
502 
503  } else if (digit1 > digit2) {
504  rc = 1;
505  break;
506  }
507 
508  if (ver1_iter != NULL && *ver1_iter == '.') {
509  ver1_iter++;
510  }
511  if (ver1_iter != NULL && *ver1_iter == '\0') {
512  ver1_iter = NULL;
513  }
514 
515  if (ver2_iter != NULL && *ver2_iter == '.') {
516  ver2_iter++;
517  }
518  if (ver2_iter != NULL && *ver2_iter == 0) {
519  ver2_iter = NULL;
520  }
521  }
522 
523  if (rc == 0) {
524  crm_trace("%s == %s (%d)", version1, version2, lpc);
525  } else if (rc < 0) {
526  crm_trace("%s < %s (%d)", version1, version2, lpc);
527  } else if (rc > 0) {
528  crm_trace("%s > %s (%d)", version1, version2, lpc);
529  }
530 
531  return rc;
532 }
533 
534 gboolean do_stderr = FALSE;
535 
536 #ifndef NUMCHARS
537 # define NUMCHARS "0123456789."
538 #endif
539 
540 #ifndef WHITESPACE
541 # define WHITESPACE " \t\n\r\f"
542 #endif
543 
544 guint
545 crm_parse_interval_spec(const char *input)
546 {
547  long long msec = 0;
548 
549  if (input == NULL) {
550  return 0;
551 
552  } else if (input[0] != 'P') {
553  long long tmp = crm_get_msec(input);
554 
555  if(tmp > 0) {
556  msec = tmp;
557  }
558 
559  } else {
560  crm_time_t *period_s = crm_time_parse_duration(input);
561 
562  if (period_s) {
563  msec = 1000 * crm_time_get_seconds(period_s);
564  crm_time_free(period_s);
565  } else {
566  // Reason why not valid has already been logged
567  crm_warn("Using 0 instead of '%s'", input);
568  }
569  }
570 
571  return (msec <= 0)? 0 : ((msec >= G_MAXUINT)? G_MAXUINT : (guint) msec);
572 }
573 
574 long long
575 crm_get_msec(const char *input)
576 {
577  const char *cp = input;
578  const char *units;
579  long long multiplier = 1000;
580  long long divisor = 1;
581  long long msec = -1;
582  char *end_text = NULL;
583 
584  /* double dret; */
585 
586  if (input == NULL) {
587  return msec;
588  }
589 
590  cp += strspn(cp, WHITESPACE);
591  units = cp + strspn(cp, NUMCHARS);
592  units += strspn(units, WHITESPACE);
593 
594  if (strchr(NUMCHARS, *cp) == NULL) {
595  return msec;
596  }
597 
598  if (strncasecmp(units, "ms", 2) == 0 || strncasecmp(units, "msec", 4) == 0) {
599  multiplier = 1;
600  divisor = 1;
601  } else if (strncasecmp(units, "us", 2) == 0 || strncasecmp(units, "usec", 4) == 0) {
602  multiplier = 1;
603  divisor = 1000;
604  } else if (strncasecmp(units, "s", 1) == 0 || strncasecmp(units, "sec", 3) == 0) {
605  multiplier = 1000;
606  divisor = 1;
607  } else if (strncasecmp(units, "m", 1) == 0 || strncasecmp(units, "min", 3) == 0) {
608  multiplier = 60 * 1000;
609  divisor = 1;
610  } else if (strncasecmp(units, "h", 1) == 0 || strncasecmp(units, "hr", 2) == 0) {
611  multiplier = 60 * 60 * 1000;
612  divisor = 1;
613  } else if (*units != EOS && *units != '\n' && *units != '\r') {
614  return msec;
615  }
616 
617  msec = crm_int_helper(cp, &end_text);
618  if (msec > LLONG_MAX/multiplier) {
619  /* arithmetics overflow while multiplier/divisor mutually exclusive */
620  return LLONG_MAX;
621  }
622  msec *= multiplier;
623  msec /= divisor;
624  /* dret += 0.5; */
625  /* msec = (long long)dret; */
626  return msec;
627 }
628 
629 extern bool crm_is_daemon;
630 
631 /* coverity[+kill] */
632 void
633 crm_abort(const char *file, const char *function, int line,
634  const char *assert_condition, gboolean do_core, gboolean do_fork)
635 {
636  int rc = 0;
637  int pid = 0;
638  int status = 0;
639 
640  /* Implied by the parent's error logging below */
641  /* crm_write_blackbox(0); */
642 
643  if(crm_is_daemon == FALSE) {
644  /* This is a command line tool - do not fork */
645 
646  /* crm_add_logfile(NULL); * Record it to a file? */
647  crm_enable_stderr(TRUE); /* Make sure stderr is enabled so we can tell the caller */
648  do_fork = FALSE; /* Just crash if needed */
649  }
650 
651  if (do_core == FALSE) {
652  crm_err("%s: Triggered assert at %s:%d : %s", function, file, line, assert_condition);
653  return;
654 
655  } else if (do_fork) {
656  pid = fork();
657 
658  } else {
659  crm_err("%s: Triggered fatal assert at %s:%d : %s", function, file, line, assert_condition);
660  }
661 
662  if (pid == -1) {
663  crm_crit("%s: Cannot create core for non-fatal assert at %s:%d : %s",
664  function, file, line, assert_condition);
665  return;
666 
667  } else if(pid == 0) {
668  /* Child process */
669  abort();
670  return;
671  }
672 
673  /* Parent process */
674  crm_err("%s: Forked child %d to record non-fatal assert at %s:%d : %s",
675  function, pid, file, line, assert_condition);
676  crm_write_blackbox(SIGTRAP, NULL);
677 
678  do {
679  rc = waitpid(pid, &status, 0);
680  if(rc == pid) {
681  return; /* Job done */
682  }
683 
684  } while(errno == EINTR);
685 
686  if (errno == ECHILD) {
687  /* crm_mon does this */
688  crm_trace("Cannot wait on forked child %d - SIGCHLD is probably set to SIG_IGN", pid);
689  return;
690  }
691  crm_perror(LOG_ERR, "Cannot wait on forked child %d", pid);
692 }
693 
694 void
695 crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
696 {
697  int rc;
698  long pid;
699  const char *devnull = "/dev/null";
700 
701  if (daemonize == FALSE) {
702  return;
703  }
704 
705  /* Check before we even try... */
706  rc = crm_pidfile_inuse(pidfile, 1, name);
707  if(rc < pcmk_ok && rc != -ENOENT) {
708  pid = crm_read_pidfile(pidfile);
709  crm_err("%s: already running [pid %ld in %s]", name, pid, pidfile);
710  printf("%s: already running [pid %ld in %s]\n", name, pid, pidfile);
712  }
713 
714  pid = fork();
715  if (pid < 0) {
716  fprintf(stderr, "%s: could not start daemon\n", name);
717  crm_perror(LOG_ERR, "fork");
719 
720  } else if (pid > 0) {
722  }
723 
724  rc = crm_lock_pidfile(pidfile, name);
725  if(rc < pcmk_ok) {
726  crm_err("Could not lock '%s' for %s: %s (%d)", pidfile, name, pcmk_strerror(rc), rc);
727  printf("Could not lock '%s' for %s: %s (%d)\n", pidfile, name, pcmk_strerror(rc), rc);
729  }
730 
731  umask(S_IWGRP | S_IWOTH | S_IROTH);
732 
733  close(STDIN_FILENO);
734  (void)open(devnull, O_RDONLY); /* Stdin: fd 0 */
735  close(STDOUT_FILENO);
736  (void)open(devnull, O_WRONLY); /* Stdout: fd 1 */
737  close(STDERR_FILENO);
738  (void)open(devnull, O_WRONLY); /* Stderr: fd 2 */
739 }
740 
741 char *
742 crm_meta_name(const char *field)
743 {
744  int lpc = 0;
745  int max = 0;
746  char *crm_name = NULL;
747 
748  CRM_CHECK(field != NULL, return NULL);
749  crm_name = crm_concat(CRM_META, field, '_');
750 
751  /* Massage the names so they can be used as shell variables */
752  max = strlen(crm_name);
753  for (; lpc < max; lpc++) {
754  switch (crm_name[lpc]) {
755  case '-':
756  crm_name[lpc] = '_';
757  break;
758  }
759  }
760  return crm_name;
761 }
762 
763 const char *
764 crm_meta_value(GHashTable * hash, const char *field)
765 {
766  char *key = NULL;
767  const char *value = NULL;
768 
769  key = crm_meta_name(field);
770  if (key) {
771  value = g_hash_table_lookup(hash, key);
772  free(key);
773  }
774 
775  return value;
776 }
777 
778 static struct option *
779 crm_create_long_opts(struct crm_option *long_options)
780 {
781  struct option *long_opts = NULL;
782 
783 #ifdef HAVE_GETOPT_H
784  int index = 0, lpc = 0;
785 
786  /*
787  * A previous, possibly poor, choice of '?' as the short form of --help
788  * means that getopt_long() returns '?' for both --help and for "unknown option"
789  *
790  * This dummy entry allows us to differentiate between the two in crm_get_option()
791  * and exit with the correct error code
792  */
793  long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option));
794  long_opts[index].name = "__dummmy__";
795  long_opts[index].has_arg = 0;
796  long_opts[index].flag = 0;
797  long_opts[index].val = '_';
798  index++;
799 
800  for (lpc = 0; long_options[lpc].name != NULL; lpc++) {
801  if (long_options[lpc].name[0] == '-') {
802  continue;
803  }
804 
805  long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option));
806  /*fprintf(stderr, "Creating %d %s = %c\n", index,
807  * long_options[lpc].name, long_options[lpc].val); */
808  long_opts[index].name = long_options[lpc].name;
809  long_opts[index].has_arg = long_options[lpc].has_arg;
810  long_opts[index].flag = long_options[lpc].flag;
811  long_opts[index].val = long_options[lpc].val;
812  index++;
813  }
814 
815  /* Now create the list terminator */
816  long_opts = realloc_safe(long_opts, (index + 1) * sizeof(struct option));
817  long_opts[index].name = NULL;
818  long_opts[index].has_arg = 0;
819  long_opts[index].flag = 0;
820  long_opts[index].val = 0;
821 #endif
822 
823  return long_opts;
824 }
825 
826 void
827 crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options,
828  const char *app_desc)
829 {
830  if (short_options) {
831  crm_short_options = strdup(short_options);
832 
833  } else if (long_options) {
834  int lpc = 0;
835  int opt_string_len = 0;
836  char *local_short_options = NULL;
837 
838  for (lpc = 0; long_options[lpc].name != NULL; lpc++) {
839  if (long_options[lpc].val && long_options[lpc].val != '-' && long_options[lpc].val < UCHAR_MAX) {
840  local_short_options = realloc_safe(local_short_options, opt_string_len + 4);
841  local_short_options[opt_string_len++] = long_options[lpc].val;
842  /* getopt(3) says: Two colons mean an option takes an optional arg; */
843  if (long_options[lpc].has_arg == optional_argument) {
844  local_short_options[opt_string_len++] = ':';
845  }
846  if (long_options[lpc].has_arg >= required_argument) {
847  local_short_options[opt_string_len++] = ':';
848  }
849  local_short_options[opt_string_len] = 0;
850  }
851  }
852  crm_short_options = local_short_options;
853  crm_trace("Generated short option string: '%s'", local_short_options);
854  }
855 
856  if (long_options) {
857  crm_long_options = long_options;
858  }
859  if (app_desc) {
860  crm_app_description = app_desc;
861  }
862  if (app_usage) {
863  crm_app_usage = app_usage;
864  }
865 }
866 
867 int
868 crm_get_option(int argc, char **argv, int *index)
869 {
870  return crm_get_option_long(argc, argv, index, NULL);
871 }
872 
873 int
874 crm_get_option_long(int argc, char **argv, int *index, const char **longname)
875 {
876 #ifdef HAVE_GETOPT_H
877  static struct option *long_opts = NULL;
878 
879  if (long_opts == NULL && crm_long_options) {
880  long_opts = crm_create_long_opts(crm_long_options);
881  }
882 
883  *index = 0;
884  if (long_opts) {
885  int flag = getopt_long(argc, argv, crm_short_options, long_opts, index);
886 
887  switch (flag) {
888  case 0:
889  if (long_opts[*index].val) {
890  return long_opts[*index].val;
891  } else if (longname) {
892  *longname = long_opts[*index].name;
893  } else {
894  crm_notice("Unhandled option --%s", long_opts[*index].name);
895  return flag;
896  }
897  case -1: /* End of option processing */
898  break;
899  case ':':
900  crm_trace("Missing argument");
901  crm_help('?', CRM_EX_USAGE);
902  break;
903  case '?':
904  crm_help('?', (*index? CRM_EX_OK : CRM_EX_USAGE));
905  break;
906  }
907  return flag;
908  }
909 #endif
910 
911  if (crm_short_options) {
912  return getopt(argc, argv, crm_short_options);
913  }
914 
915  return -1;
916 }
917 
918 void
919 crm_help(char cmd, crm_exit_t exit_code)
920 {
921  int i = 0;
922  FILE *stream = (exit_code ? stderr : stdout);
923 
924  if (cmd == 'v' || cmd == '$') {
925  fprintf(stream, "Pacemaker %s\n", PACEMAKER_VERSION);
926  fprintf(stream, "Written by Andrew Beekhof\n");
927  goto out;
928  }
929 
930  if (cmd == '!') {
931  fprintf(stream, "Pacemaker %s (Build: %s): %s\n", PACEMAKER_VERSION, BUILD_VERSION, CRM_FEATURES);
932  goto out;
933  }
934 
935  fprintf(stream, "%s - %s\n", crm_system_name, crm_app_description);
936 
937  if (crm_app_usage) {
938  fprintf(stream, "Usage: %s %s\n", crm_system_name, crm_app_usage);
939  }
940 
941  if (crm_long_options) {
942  fprintf(stream, "Options:\n");
943  for (i = 0; crm_long_options[i].name != NULL; i++) {
944  if (crm_long_options[i].flags & pcmk_option_hidden) {
945 
946  } else if (crm_long_options[i].flags & pcmk_option_paragraph) {
947  fprintf(stream, "%s\n\n", crm_long_options[i].desc);
948 
949  } else if (crm_long_options[i].flags & pcmk_option_example) {
950  fprintf(stream, "\t#%s\n\n", crm_long_options[i].desc);
951 
952  } else if (crm_long_options[i].val == '-' && crm_long_options[i].desc) {
953  fprintf(stream, "%s\n", crm_long_options[i].desc);
954 
955  } else {
956  /* is val printable as char ? */
957  if (crm_long_options[i].val && crm_long_options[i].val <= UCHAR_MAX) {
958  fprintf(stream, " -%c,", crm_long_options[i].val);
959  } else {
960  fputs(" ", stream);
961  }
962  fprintf(stream, " --%s%s\t%s\n", crm_long_options[i].name,
963  crm_long_options[i].has_arg == optional_argument ? "[=value]" :
964  crm_long_options[i].has_arg == required_argument ? "=value" : "",
965  crm_long_options[i].desc ? crm_long_options[i].desc : "");
966  }
967  }
968 
969  } else if (crm_short_options) {
970  fprintf(stream, "Usage: %s - %s\n", crm_system_name, crm_app_description);
971  for (i = 0; crm_short_options[i] != 0; i++) {
972  int has_arg = no_argument /* 0 */;
973 
974  if (crm_short_options[i + 1] == ':') {
975  if (crm_short_options[i + 2] == ':')
976  has_arg = optional_argument /* 2 */;
977  else
978  has_arg = required_argument /* 1 */;
979  }
980 
981  fprintf(stream, " -%c %s\n", crm_short_options[i],
982  has_arg == optional_argument ? "[value]" :
983  has_arg == required_argument ? "{value}" : "");
984  i += has_arg;
985  }
986  }
987 
988  fprintf(stream, "\nReport bugs to %s\n", PACKAGE_BUGREPORT);
989 
990  out:
991  crm_exit(exit_code);
992  while(1); // above does not return
993 }
994 
995 void cib_ipc_servers_init(qb_ipcs_service_t **ipcs_ro,
996  qb_ipcs_service_t **ipcs_rw,
997  qb_ipcs_service_t **ipcs_shm,
998  struct qb_ipcs_service_handlers *ro_cb,
999  struct qb_ipcs_service_handlers *rw_cb)
1000 {
1001  *ipcs_ro = mainloop_add_ipc_server(CIB_CHANNEL_RO, QB_IPC_NATIVE, ro_cb);
1002  *ipcs_rw = mainloop_add_ipc_server(CIB_CHANNEL_RW, QB_IPC_NATIVE, rw_cb);
1003  *ipcs_shm = mainloop_add_ipc_server(CIB_CHANNEL_SHM, QB_IPC_SHM, rw_cb);
1004 
1005  if (*ipcs_ro == NULL || *ipcs_rw == NULL || *ipcs_shm == NULL) {
1006  crm_err("Failed to create the CIB manager: exiting and inhibiting respawn");
1007  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled");
1009  }
1010 }
1011 
1012 void cib_ipc_servers_destroy(qb_ipcs_service_t *ipcs_ro,
1013  qb_ipcs_service_t *ipcs_rw,
1014  qb_ipcs_service_t *ipcs_shm)
1015 {
1016  qb_ipcs_destroy(ipcs_ro);
1017  qb_ipcs_destroy(ipcs_rw);
1018  qb_ipcs_destroy(ipcs_shm);
1019 }
1020 
1021 qb_ipcs_service_t *
1022 crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb)
1023 {
1024  return mainloop_add_ipc_server(CRM_SYSTEM_CRMD, QB_IPC_NATIVE, cb);
1025 }
1026 
1027 void
1028 attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
1029 {
1030  *ipcs = mainloop_add_ipc_server(T_ATTRD, QB_IPC_NATIVE, cb);
1031 
1032  if (*ipcs == NULL) {
1033  crm_err("Failed to create pacemaker-attrd server: exiting and inhibiting respawn");
1034  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1036  }
1037 }
1038 
1039 void
1040 stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
1041 {
1042  *ipcs = mainloop_add_ipc_server_with_prio("stonith-ng", QB_IPC_NATIVE, cb,
1043  QB_LOOP_HIGH);
1044 
1045  if (*ipcs == NULL) {
1046  crm_err("Failed to create fencer: exiting and inhibiting respawn.");
1047  crm_warn("Verify pacemaker and pacemaker_remote are not both enabled.");
1049  }
1050 }
1051 
1052 void *
1053 find_library_function(void **handle, const char *lib, const char *fn, gboolean fatal)
1054 {
1055  char *error;
1056  void *a_function;
1057 
1058  if (*handle == NULL) {
1059  *handle = dlopen(lib, RTLD_LAZY);
1060  }
1061 
1062  if (!(*handle)) {
1063  crm_err("%sCould not open %s: %s", fatal ? "Fatal: " : "", lib, dlerror());
1064  if (fatal) {
1066  }
1067  return NULL;
1068  }
1069 
1070  a_function = dlsym(*handle, fn);
1071  if (a_function == NULL) {
1072  error = dlerror();
1073  crm_err("%sCould not find %s in %s: %s", fatal ? "Fatal: " : "", fn, lib, error);
1074  if (fatal) {
1076  }
1077  }
1078 
1079  return a_function;
1080 }
1081 
1082 #ifdef HAVE_UUID_UUID_H
1083 # include <uuid/uuid.h>
1084 #endif
1085 
1086 char *
1088 {
1089  unsigned char uuid[16];
1090  char *buffer = malloc(37); /* Including NUL byte */
1091 
1092  uuid_generate(uuid);
1093  uuid_unparse(uuid, buffer);
1094  return buffer;
1095 }
1096 
1108 const char *
1109 pcmk_message_name(const char *name)
1110 {
1111  if (name == NULL) {
1112  return "unknown";
1113 
1114  } else if (!strcmp(name, "pacemaker-attrd")) {
1115  return "attrd";
1116 
1117  } else if (!strcmp(name, "pacemaker-based")) {
1118  return CRM_SYSTEM_CIB;
1119 
1120  } else if (!strcmp(name, "pacemaker-controld")) {
1121  return CRM_SYSTEM_CRMD;
1122 
1123  } else if (!strcmp(name, "pacemaker-execd")) {
1124  return CRM_SYSTEM_LRMD;
1125 
1126  } else if (!strcmp(name, "pacemaker-fenced")) {
1127  return "stonith-ng";
1128 
1129  } else if (!strcmp(name, "pacemaker-schedulerd")) {
1130  return CRM_SYSTEM_PENGINE;
1131 
1132  } else {
1133  return name;
1134  }
1135 }
1136 
1144 bool
1145 crm_is_daemon_name(const char *name)
1146 {
1147  name = pcmk_message_name(name);
1148  return (!strcmp(name, CRM_SYSTEM_CRMD)
1149  || !strcmp(name, CRM_SYSTEM_STONITHD)
1150  || !strcmp(name, "stonith-ng")
1151  || !strcmp(name, "attrd")
1152  || !strcmp(name, CRM_SYSTEM_CIB)
1153  || !strcmp(name, CRM_SYSTEM_MCP)
1154  || !strcmp(name, CRM_SYSTEM_DC)
1155  || !strcmp(name, CRM_SYSTEM_TENGINE)
1156  || !strcmp(name, CRM_SYSTEM_LRMD));
1157 }
1158 
1159 #include <md5.h>
1160 
1161 char *
1162 crm_md5sum(const char *buffer)
1163 {
1164  int lpc = 0, len = 0;
1165  char *digest = NULL;
1166  unsigned char raw_digest[MD5_DIGEST_SIZE];
1167 
1168  if (buffer == NULL) {
1169  buffer = "";
1170  }
1171  len = strlen(buffer);
1172 
1173  crm_trace("Beginning digest of %d bytes", len);
1174  digest = malloc(2 * MD5_DIGEST_SIZE + 1);
1175  if(digest) {
1176  md5_buffer(buffer, len, raw_digest);
1177  for (lpc = 0; lpc < MD5_DIGEST_SIZE; lpc++) {
1178  sprintf(digest + (2 * lpc), "%02x", raw_digest[lpc]);
1179  }
1180  digest[(2 * MD5_DIGEST_SIZE)] = 0;
1181  crm_trace("Digest %s.", digest);
1182 
1183  } else {
1184  crm_err("Could not create digest");
1185  }
1186  return digest;
1187 }
1188 
1189 #ifdef HAVE_GNUTLS_GNUTLS_H
1190 void
1191 crm_gnutls_global_init(void)
1192 {
1193  signal(SIGPIPE, SIG_IGN);
1194  gnutls_global_init();
1195 }
1196 #endif
1197 
1203 char *
1205 {
1206  struct utsname hostinfo;
1207 
1208  return (uname(&hostinfo) < 0)? NULL : strdup(hostinfo.nodename);
1209 }
CRM_SYSTEM_PENGINE
#define CRM_SYSTEM_PENGINE
Definition: crm.h:105
CRM_MINUS_INFINITY_S
#define CRM_MINUS_INFINITY_S
Definition: crm.h:85
CRM_EX_OK
@ CRM_EX_OK
Definition: results.h:111
crm_help
void crm_help(char cmd, crm_exit_t exit_code)
Definition: utils.c:919
crm_config_warning
gboolean crm_config_warning
Definition: utils.c:60
verify_all_options
void verify_all_options(GHashTable *options, pe_cluster_option *option_list, int len)
Definition: utils.c:382
check_boolean
gboolean check_boolean(const char *value)
Definition: utils.c:91
crm_option
Definition: crm_internal.h:61
CRM_EX_ERROR
@ CRM_EX_ERROR
Definition: results.h:112
crm_get_option_long
int crm_get_option_long(int argc, char **argv, int *index, const char **longname)
Definition: utils.c:874
flags
uint64_t flags
Definition: remote.c:5
do_stderr
gboolean do_stderr
Definition: utils.c:534
msg_xml.h
crm_set_options
void crm_set_options(const char *short_options, const char *app_usage, struct crm_option *long_options, const char *app_desc)
Definition: utils.c:827
crm_lock_pidfile
int crm_lock_pidfile(const char *filename, const char *name)
Definition: pid.c:168
BUILD_VERSION
#define BUILD_VERSION
Definition: config.h:8
crm_write_blackbox
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
Definition: logging.c:457
CRM_SYSTEM_MCP
#define CRM_SYSTEM_MCP
Definition: crm.h:108
crm_md5sum
char * crm_md5sum(const char *buffer)
Definition: utils.c:1162
crm_str_to_boolean
int crm_str_to_boolean(const char *s, int *ret)
Definition: strings.c:187
attrd_ipc_server_init
void attrd_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: utils.c:1028
CRM_SYSTEM_CRMD
#define CRM_SYSTEM_CRMD
Definition: crm.h:103
CRM_SYSTEM_TENGINE
#define CRM_SYSTEM_TENGINE
Definition: crm.h:106
find_library_function
void * find_library_function(void **handle, const char *lib, const char *fn, gboolean fatal)
Definition: utils.c:1053
CRM_SYSTEM_DC
#define CRM_SYSTEM_DC
Definition: crm.h:99
crm_time_parse_duration
crm_time_t * crm_time_parse_duration(const char *duration_str)
Parse a time duration from an ISO 8601 duration specification.
Definition: iso8601.c:987
crm_crit
#define crm_crit(fmt, args...)
Definition: logging.h:240
crm_make_daemon
void crm_make_daemon(const char *name, gboolean daemonize, const char *pidfile)
Definition: utils.c:695
pcmk_strerror
const char * pcmk_strerror(int rc)
Definition: results.c:188
crm_meta_name
char * crm_meta_name(const char *field)
Definition: utils.c:742
CRM_CHECK
#define CRM_CHECK(expr, failure_action)
Definition: logging.h:157
CRM_SYSTEM_CIB
#define CRM_SYSTEM_CIB
Definition: crm.h:102
get_cluster_pref
const char * get_cluster_pref(GHashTable *options, pe_cluster_option *option_list, int len, const char *name)
Definition: utils.c:328
crm_notice
#define crm_notice(fmt, args...)
Definition: logging.h:243
type
enum crm_ais_msg_types type
Definition: internal.h:5
crm_err
#define crm_err(fmt, args...)
Definition: logging.h:241
crm_itoa_stack
char * crm_itoa_stack(int an_int, char *buf, size_t len)
Definition: strings.c:24
cib_ipc_servers_destroy
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:1012
crm_trace
#define crm_trace(fmt, args...)
Definition: logging.h:247
safe_str_eq
#define safe_str_eq(a, b)
Definition: util.h:61
pcmk_message_name
const char * pcmk_message_name(const char *name)
Get name to be used as identifier for cluster messages.
Definition: utils.c:1109
crm_option::has_arg
int has_arg
Definition: crm_internal.h:69
crm_warn
#define crm_warn(fmt, args...)
Definition: logging.h:242
CIB_CHANNEL_RO
#define CIB_CHANNEL_RO
Definition: internal.h:69
stonith_ipc_server_init
void stonith_ipc_server_init(qb_ipcs_service_t **ipcs, struct qb_ipcs_service_handlers *cb)
Definition: utils.c:1040
check_time
gboolean check_time(const char *value)
Definition: utils.c:73
pcmk_option_example
#define pcmk_option_example
Definition: crm_internal.h:59
xml.h
Wrappers for and extensions to libxml2.
CRM_EX_OSERR
@ CRM_EX_OSERR
Definition: results.h:130
crm_system_name
char * crm_system_name
Definition: utils.c:61
cib_ipc_servers_init
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:995
internal.h
mainloop.h
Wrappers for and extensions to glib mainloop.
crm_is_daemon_name
bool crm_is_daemon_name(const char *name)
Check whether a string represents a cluster daemon name.
Definition: utils.c:1145
NUMCHARS
#define NUMCHARS
Definition: utils.c:537
CRM_SYSTEM_STONITHD
#define CRM_SYSTEM_STONITHD
Definition: crm.h:107
check_positive_number
gboolean check_positive_number(const char *value)
Definition: utils.c:123
node_score_red
int node_score_red
Definition: utils.c:63
crm_is_daemon
bool crm_is_daemon
Definition: logging.c:40
config_metadata
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:347
CRM_PLUS_INFINITY_S
#define CRM_PLUS_INFINITY_S
Definition: crm.h:84
mainloop_add_ipc_server
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:702
CRM_META
#define CRM_META
Definition: crm.h:72
check_quorum
gboolean check_quorum(const char *value)
Definition: utils.c:132
crm_info
#define crm_info(fmt, args...)
Definition: logging.h:244
CRM_INFINITY_S
#define CRM_INFINITY_S
Definition: crm.h:83
PW_BUFFER_LEN
#define PW_BUFFER_LEN
Definition: utils.c:54
generate_hash_key
char * generate_hash_key(const char *crm_msg_reference, const char *sys)
Definition: utils.c:395
uname
char uname[MAX_NAME]
Definition: internal.h:7
CRM_TRACE_INIT_DATA
CRM_TRACE_INIT_DATA(common)
crm_parse_interval_spec
guint crm_parse_interval_spec(const char *input)
Definition: utils.c:545
CRM_SYSTEM_LRMD
#define CRM_SYSTEM_LRMD
Definition: crm.h:104
check_script
gboolean check_script(const char *value)
Definition: utils.c:153
EOS
#define EOS
Definition: crm.h:57
pid
uint32_t pid
Definition: internal.h:3
cluster_option
const char * cluster_option(GHashTable *options, gboolean(*validate)(const char *), const char *name, const char *old_name, const char *def_value)
Definition: utils.c:266
T_ATTRD
#define T_ATTRD
Definition: msg_xml.h:46
crm_enable_stderr
void crm_enable_stderr(int enable)
Definition: logging.c:949
CRM_FEATURES
#define CRM_FEATURES
Definition: config.h:35
check_timer
gboolean check_timer(const char *value)
Definition: utils.c:82
crm_pidfile_inuse
long crm_pidfile_inuse(const char *filename, long mypid, const char *daemon)
Definition: pid.c:141
iso8601.h
ISO_8601 Date handling.
node_score_yellow
int node_score_yellow
Definition: utils.c:65
MD5_DIGEST_SIZE
#define MD5_DIGEST_SIZE
Definition: md5.h:30
WHITESPACE
#define WHITESPACE
Definition: utils.c:541
PACKAGE_BUGREPORT
#define PACKAGE_BUGREPORT
Definition: config.h:523
compare_version
int compare_version(const char *version1, const char *version2)
Definition: utils.c:464
score2char
char * score2char(int score)
Definition: utils.c:254
mainloop_add_ipc_server_with_prio
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:709
crm_generate_uuid
char * crm_generate_uuid(void)
Definition: utils.c:1087
crm_args_fini
void crm_args_fini()
Definition: utils.c:195
crm_option::flag
int * flag
Definition: crm_internal.h:71
ipc.h
Wrappers for and extensions to libqb IPC.
pe_cluster_option_s
Definition: crm_internal.h:87
pcmk_option_paragraph
#define pcmk_option_paragraph
Definition: crm_internal.h:58
crm_parse_int
int crm_parse_int(const char *text, const char *default_text)
Parse an integer value from a string.
Definition: strings.c:114
crm_perror
#define crm_perror(level, fmt, args...)
Log a system error message.
Definition: logging.h:219
char2score
int char2score(const char *score)
Definition: utils.c:202
CRM_SCORE_INFINITY
#define CRM_SCORE_INFINITY
Definition: crm.h:82
crm_config_warn
#define crm_config_warn(fmt...)
Definition: crm_internal.h:180
md5.h
crm_option::name
const char * name
Definition: crm_internal.h:64
services.h
Services API.
CIB_CHANNEL_RW
#define CIB_CHANNEL_RW
Definition: internal.h:70
crm_abort
void crm_abort(const char *file, const char *function, int line, const char *assert_condition, gboolean do_core, gboolean do_fork)
Definition: utils.c:633
crm_exit_t
enum crm_exit_e crm_exit_t
pcmk_option_hidden
#define pcmk_option_hidden
Definition: crm_internal.h:57
node_score_green
int node_score_green
Definition: utils.c:64
CRM_ASSERT
#define CRM_ASSERT(expr)
Definition: results.h:42
crm_time_get_seconds
long long int crm_time_get_seconds(crm_time_t *dt)
Definition: iso8601.c:311
check_number
gboolean check_number(const char *value)
Definition: utils.c:102
crm_time_free
void crm_time_free(crm_time_t *dt)
Definition: iso8601.c:144
version
uint32_t version
Definition: remote.c:3
crm_get_option
int crm_get_option(int argc, char **argv, int *index)
Definition: utils.c:868
crm_option::val
int val
Definition: crm_internal.h:73
crm_read_pidfile
long crm_read_pidfile(const char *filename)
Definition: pid.c:103
score2char_stack
char * score2char_stack(int score, char *buf, size_t len)
Definition: utils.c:240
check_utilization
gboolean check_utilization(const char *value)
Definition: utils.c:180
md5_buffer
void * md5_buffer(const char *buffer, size_t len, void *resblock)
Definition: md5.c:227
crm_meta_value
const char * crm_meta_value(GHashTable *hash, const char *field)
Definition: utils.c:764
CIB_CHANNEL_SHM
#define CIB_CHANNEL_SHM
Definition: internal.h:71
crm_exit
_Noreturn crm_exit_t crm_exit(crm_exit_t rc)
Definition: results.c:478
crmd_ipc_server_init
qb_ipcs_service_t * crmd_ipc_server_init(struct qb_ipcs_service_handlers *cb)
Definition: utils.c:1022
crm_config_error
gboolean crm_config_error
Definition: utils.c:59
CRM_EX_USAGE
@ CRM_EX_USAGE
Definition: results.h:123
crm_internal.h
PACEMAKER_VERSION
#define PACEMAKER_VERSION
Definition: config.h:517
util.h
Utility functions.
pcmk_hostname
char * pcmk_hostname()
Get the local hostname.
Definition: utils.c:1204
crm.h
A dumping ground.
crm_int_helper
long long crm_int_helper(const char *text, char **end_text)
Definition: strings.c:34
crm_get_msec
long long crm_get_msec(const char *input)
Definition: utils.c:575
pcmk_ok
#define pcmk_ok
Definition: results.h:57
crm_user_lookup
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
Definition: utils.c:405
crm_time_t
struct crm_time_s crm_time_t
Definition: iso8601.h:32
crm_config_err
#define crm_config_err(fmt...)
Definition: crm_internal.h:179
CRM_EX_FATAL
@ CRM_EX_FATAL
Definition: results.h:140