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