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