cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

conversion.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 
25 
26 #include <conversion.h>
27 
28 #include <promises.h>
29 #include <files_names.h>
30 #include <dbm_api.h>
31 #include <mod_access.h>
32 #include <item_lib.h>
33 #include <logging.h>
34 #include <rlist.h>
35 #include <string_lib.h>
36 
37 
38 const char *MapAddress(const char *unspec_address)
39 { /* Is the address a mapped ipv4 over ipv6 address */
40 
41  if (strncmp(unspec_address, "::ffff:", 7) == 0)
42  {
43  return unspec_address + 7;
44  }
45  else
46  {
47  return unspec_address;
48  }
49 }
50 
51 int FindTypeInArray(const char *const haystack[], const char *needle, int default_value, int null_value)
52 {
53  if (needle == NULL)
54  {
55  return null_value;
56  }
57 
58  for (int i = 0; haystack[i] != NULL; ++i)
59  {
60  if (strcmp(needle, haystack[i]) == 0)
61  {
62  return i;
63  }
64  }
65 
66  return default_value;
67 }
68 
70 {
71  static const char *const MEASURE_POLICY_TYPES[] =
72  { "average", "sum", "first", "last", NULL };
73 
74  return FindTypeInArray(MEASURE_POLICY_TYPES, s, MEASURE_POLICY_AVERAGE, MEASURE_POLICY_NONE);
75 }
76 
78 {
79  static const char *const ENV_STATE_TYPES[] =
80  { "create", "delete", "running", "suspended", "down", NULL };
81 
83 }
84 
86 {
87  static const char *const INSERT_MATCH_TYPES[] =
88  { "ignore_leading", "ignore_trailing", "ignore_embedded",
89  "exact_match", NULL };
90 
91  return FindTypeInArray(INSERT_MATCH_TYPES, s, INSERT_MATCH_TYPE_EXACT, INSERT_MATCH_TYPE_EXACT);
92 }
93 
94 int SyslogPriorityFromString(const char *s)
95 {
96  static const char *const SYSLOG_PRIORITY_TYPES[] =
97  { "emergency", "alert", "critical", "error", "warning", "notice",
98  "info", "debug", NULL };
99 
100  return FindTypeInArray(SYSLOG_PRIORITY_TYPES, s, 3, 3);
101 }
102 
103 ShellType ShellTypeFromString(const char *string)
104 {
105  // For historical reasons, supports all CF_BOOL values (true/false/yes/no...),
106  // as well as "noshell,useshell,powershell".
107  char *start, *end;
108  char *options = "noshell,useshell,powershell," CF_BOOL;
109  int i;
110  int size;
111 
112  if (string == NULL)
113  {
114  return SHELL_TYPE_NONE;
115  }
116 
117  start = options;
118  size = strlen(string);
119  for (i = 0;; i++)
120  {
121  end = strchr(start, ',');
122  if (end == NULL)
123  {
124  break;
125  }
126  if (size == end - start && strncmp(string, start, end - start) == 0)
127  {
128  int cfBoolIndex;
129  switch (i)
130  {
131  case 0:
132  return SHELL_TYPE_NONE;
133  case 1:
134  return SHELL_TYPE_USE;
135  case 2:
136  return SHELL_TYPE_POWERSHELL;
137  default:
138  // Even cfBoolIndex is true, odd cfBoolIndex is false (from CF_BOOL).
139  cfBoolIndex = i-3;
140  return (cfBoolIndex & 1) ? SHELL_TYPE_NONE : SHELL_TYPE_USE;
141  }
142  }
143  start = end + 1;
144  }
145  return SHELL_TYPE_NONE;
146 }
147 
149 {
150  static const char *const DB_TYPES[] = { "mysql", "postgres", NULL };
151 
153 }
154 
156 {
157  static const char *const U_TYPES[] =
158  { "present", "absent", "locked", NULL };
159 
160  return FindTypeInArray(U_TYPES, s, USER_STATE_NONE, USER_STATE_NONE);
161 }
162 
164 {
165  static const char *const U_TYPES[] = { "plaintext", "hash", NULL };
166 
168 }
169 
171 {
172  static const char *const PACKAGE_ACTION_TYPES[] =
173  { "add", "delete", "reinstall", "update", "addupdate", "patch",
174  "verify", NULL };
175 
176  return FindTypeInArray(PACKAGE_ACTION_TYPES, s, PACKAGE_ACTION_NONE, PACKAGE_ACTION_NONE);
177 }
178 
179 NewPackageAction GetNewPackagePolicy(const char *s, const char **action_types)
180 {
182 }
183 
185 {
186  static const char *const PACKAGE_SELECT_TYPES[] =
187  { "==", "!=", ">", "<", ">=", "<=", NULL };
188 
190 }
191 
193 {
194  static const char *const ACTION_POLICY_TYPES[] =
195  { "individual", "bulk", NULL };
196 
198 }
199 
200 /***************************************************************************/
201 
202 char *Rlist2String(Rlist *list, char *sep)
203 {
204  Writer *writer = StringWriter();
205 
206  for (const Rlist *rp = list; rp != NULL; rp = rp->next)
207  {
208  RvalWrite(writer, rp->val);
209 
210  if (rp->next != NULL)
211  {
212  WriterWrite(writer, sep);
213  }
214  }
215 
216  return StringWriterClose(writer);
217 }
218 
219 /***************************************************************************/
220 
221 int SignalFromString(const char *s)
222 {
223  int i = 0;
224  Item *ip, *names = SplitString(CF_SIGNALRANGE, ',');
225 
226  for (ip = names; ip != NULL; ip = ip->next)
227  {
228  if (strcmp(s, ip->name) == 0)
229  {
230  break;
231  }
232  i++;
233  }
234 
235  DeleteItemList(names);
236 
237  switch (i)
238  {
239  case cfa_hup:
240  return SIGHUP;
241  case cfa_int:
242  return SIGINT;
243  case cfa_trap:
244  return SIGTRAP;
245  case cfa_kill:
246  return SIGKILL;
247  case cfa_pipe:
248  return SIGPIPE;
249  case cfa_cont:
250  return SIGCONT;
251  case cfa_abrt:
252  return SIGABRT;
253  case cfa_stop:
254  return SIGSTOP;
255  case cfa_quit:
256  return SIGQUIT;
257  case cfa_term:
258  return SIGTERM;
259  case cfa_child:
260  return SIGCHLD;
261  case cfa_usr1:
262  return SIGUSR1;
263  case cfa_usr2:
264  return SIGUSR2;
265  case cfa_bus:
266  return SIGBUS;
267  case cfa_segv:
268  return SIGSEGV;
269  default:
270  return -1;
271  }
272 
273 }
274 
275 ContextScope ContextScopeFromString(const char *scope_str)
276 {
277  static const char *const CONTEXT_SCOPES[] = { "namespace", "bundle" };
278  return FindTypeInArray(CONTEXT_SCOPES, scope_str, CONTEXT_SCOPE_NAMESPACE, CONTEXT_SCOPE_NONE);
279 }
280 
282 {
283  static const char *const LINK_TYPES[] =
284  { "symlink", "hardlink", "relative", "absolute", NULL };
285 
287 }
288 
290 {
291  static const char *const FILE_COMPARISON_TYPES[] =
292  { "atime", "mtime", "ctime", "digest", "hash", "binary", "exists", NULL };
293 
294  return FindTypeInArray(FILE_COMPARISON_TYPES, s, FILE_COMPARATOR_NONE, FILE_COMPARATOR_NONE);
295 }
296 
297 static const char *const datatype_strings[] =
298 {
299  [CF_DATA_TYPE_STRING] = "string",
300  [CF_DATA_TYPE_INT] = "int",
301  [CF_DATA_TYPE_REAL] = "real",
302  [CF_DATA_TYPE_STRING_LIST] = "slist",
303  [CF_DATA_TYPE_INT_LIST] = "ilist",
304  [CF_DATA_TYPE_REAL_LIST] = "rlist",
305  [CF_DATA_TYPE_OPTION] = "option",
306  [CF_DATA_TYPE_OPTION_LIST] = "olist",
307  [CF_DATA_TYPE_BODY] = "body",
308  [CF_DATA_TYPE_BUNDLE] = "bundle",
309  [CF_DATA_TYPE_CONTEXT] = "context",
310  [CF_DATA_TYPE_CONTEXT_LIST] = "clist",
311  [CF_DATA_TYPE_INT_RANGE] = "irange",
312  [CF_DATA_TYPE_REAL_RANGE] = "rrange",
313  [CF_DATA_TYPE_COUNTER] = "counter",
314  [CF_DATA_TYPE_CONTAINER] = "data",
315  [CF_DATA_TYPE_NONE] = "none"
316 };
317 
318 DataType DataTypeFromString(const char *name)
319 {
320  for (int i = 0; i < CF_DATA_TYPE_NONE; i++)
321  {
322  if (strcmp(datatype_strings[i], name) == 0)
323  {
324  return i;
325  }
326  }
327 
328  return CF_DATA_TYPE_NONE;
329 }
330 
331 const char *DataTypeToString(DataType type)
332 {
333  assert(type < CF_DATA_TYPE_NONE);
334  return datatype_strings[type];
335 }
336 
337 DataType ConstraintSyntaxGetDataType(const ConstraintSyntax *body_syntax, const char *lval)
338 {
339  int i = 0;
340 
341  for (i = 0; body_syntax[i].lval != NULL; i++)
342  {
343  if (lval && (strcmp(body_syntax[i].lval, lval) == 0))
344  {
345  return body_syntax[i].dtype;
346  }
347  }
348 
349  return CF_DATA_TYPE_NONE;
350 }
351 
352 /****************************************************************************/
353 
354 bool BooleanFromString(const char *s)
355 {
356  Item *list = SplitString(CF_BOOL, ','), *ip;
357  int count = 0;
358 
359  for (ip = list; ip != NULL; ip = ip->next)
360  {
361  if (strcmp(s, ip->name) == 0)
362  {
363  break;
364  }
365 
366  count++;
367  }
368 
369  DeleteItemList(list);
370 
371  if (count % 2)
372  {
373  return false;
374  }
375  else
376  {
377  return true;
378  }
379 }
380 
381 /****************************************************************************/
382 
383 /**
384  * @NOTE parameter #s might be NULL. It's already used by design like that,
385  * for example parsing inexistent attributes in GetVolumeConstraints().
386  *
387  * @TODO see DoubleFromString(): return bool, have a value_out parameter, and
388  * kill CF_NOINT (goes deep!)
389  */
390 long IntFromString(const char *s)
391 {
392  long long ll = CF_NOINT;
393  char quantifier, remainder;
394 
395  if (s == NULL)
396  {
397  return CF_NOINT;
398  }
399  if (strcmp(s, "inf") == 0)
400  {
401  return (long) CF_INFINITY;
402  }
403  if (strcmp(s, "now") == 0)
404  {
405  return (long) CFSTARTTIME;
406  }
407 
408  int ret = sscanf(s, "%lld%c %c", &ll, &quantifier, &remainder);
409 
410  if (ret < 1 || ll == CF_NOINT)
411  {
412  if (strchr(s, '$') != NULL) /* don't log error, might converge */
413  {
415  "Ignoring failed to parse integer '%s'"
416  " because of possibly unexpanded variable", s);
417  }
418  else
419  {
420  Log(LOG_LEVEL_ERR, "Failed to parse integer number: %s", s);
421  }
422  }
423  else if (ret == 3)
424  {
425  ll = CF_NOINT;
426  if (quantifier == '$') /* don't log error, might converge */
427  {
429  "Ignoring failed to parse integer '%s'"
430  " because of possibly unexpanded variable", s);
431  }
432  else
433  {
435  "Anomalous ending '%c%c' while parsing integer number: %s",
436  quantifier, remainder, s);
437  }
438  }
439  else if (ret == 1) /* no quantifier */
440  {
441  /* nop */
442  }
443  else
444  {
445  assert(ret == 2);
446 
447  switch (quantifier)
448  {
449  case 'k':
450  ll *= 1000;
451  break;
452  case 'K':
453  ll *= 1024;
454  break;
455  case 'm':
456  ll *= 1000 * 1000;
457  break;
458  case 'M':
459  ll *= 1024 * 1024;
460  break;
461  case 'g':
462  ll *= 1000 * 1000 * 1000;
463  break;
464  case 'G':
465  ll *= 1024 * 1024 * 1024;
466  break;
467  case '%':
468  if ((ll < 0) || (ll > 100))
469  {
470  Log(LOG_LEVEL_ERR, "Percentage out of range: %lld", ll);
471  return CF_NOINT;
472  }
473  else
474  {
475  /* Represent percentages internally as negative numbers */
476  /* TODO fix? */
477  ll *= -1;
478  }
479  break;
480 
481  case ' ':
482  break;
483 
484  default:
486  "Ignoring bad quantifier '%c' in integer: %s",
487  quantifier, s);
488  break;
489  }
490  }
491 
492  /* TODO Use strtol() instead of scanf(), it properly checks for overflow
493  * but it is prone to coding errors, so even better bring OpenBSD's
494  * strtonum() for proper conversions. */
495 
496  if (ll < LONG_MIN)
497  {
499  "Number '%s' underflows a long int, truncating to %ld",
500  s, LONG_MIN);
501  return LONG_MIN;
502  }
503  else if (ll > LONG_MAX)
504  {
506  "Number '%s' overflows a long int, truncating to %ld",
507  s, LONG_MAX);
508  return LONG_MAX;
509  }
510 
511  return (long) ll;
512 }
513 
514 Interval IntervalFromString(const char *string)
515 {
516  static const char *const INTERVAL_TYPES[] = { "hourly", "daily", NULL };
517 
518  return FindTypeInArray(INTERVAL_TYPES, string, INTERVAL_NONE, INTERVAL_NONE);
519 }
520 
521 bool DoubleFromString(const char *s, double *value_out)
522 {
523  double d;
524  char quantifier, remainder;
525 
526  assert(s != NULL);
527  assert(value_out != NULL);
528 
529  int ret = sscanf(s, "%lf%c %c", &d, &quantifier, &remainder);
530 
531  if (ret < 1)
532  {
533  Log(LOG_LEVEL_ERR, "Failed to parse real number: %s", s);
534  return false;
535  }
536  else if (ret == 3) /* non-space remainder */
537  {
539  "Anomalous ending '%c%c' while parsing real number: %s",
540  quantifier, remainder, s);
541  return false;
542  }
543  else if (ret == 1) /* no quantifier char */
544  {
545  /* nop */
546  }
547  else /* got quantifier */
548  {
549  assert(ret == 2);
550 
551  switch (quantifier)
552  {
553  case 'k':
554  d *= 1000;
555  break;
556  case 'K':
557  d *= 1024;
558  break;
559  case 'm':
560  d *= 1000 * 1000;
561  break;
562  case 'M':
563  d *= 1024 * 1024;
564  break;
565  case 'g':
566  d *= 1000 * 1000 * 1000;
567  break;
568  case 'G':
569  d *= 1024 * 1024 * 1024;
570  break;
571  case '%':
572  if ((d < 0) || (d > 100))
573  {
574  Log(LOG_LEVEL_ERR, "Percentage out of range: %.2lf", d);
575  return false;
576  }
577  else
578  {
579  /* Represent percentages internally as negative numbers */
580  /* TODO fix? */
581  d *= -1;
582  }
583  break;
584 
585  case ' ':
586  break;
587 
588  default:
590  "Ignoring bad quantifier '%c' in real number: %s",
591  quantifier, s);
592  break;
593  }
594  }
595 
596  assert(ret == 1 || ret == 2);
597 
598  *value_out = d;
599  return true;
600 }
601 
602 /****************************************************************************/
603 
604 /**
605  * @return true if successful
606  */
607 bool IntegerRangeFromString(const char *intrange, long *min_out, long *max_out)
608 {
609  Item *split;
610  long lmax = CF_LOWINIT, lmin = CF_HIGHINIT;
611 
612 /* Numeric types are registered by range separated by comma str "min,max" */
613 
614  if (intrange == NULL)
615  {
616  *min_out = CF_NOINT;
617  *max_out = CF_NOINT;
618  return true;
619  }
620 
621  split = SplitString(intrange, ',');
622 
623  sscanf(split->name, "%ld", &lmin);
624 
625  if (strcmp(split->next->name, "inf") == 0)
626  {
627  lmax = (long) CF_INFINITY;
628  }
629  else
630  {
631  sscanf(split->next->name, "%ld", &lmax);
632  }
633 
634  DeleteItemList(split);
635 
636  if ((lmin == CF_HIGHINIT) || (lmax == CF_LOWINIT))
637  {
638  return false;
639  }
640 
641  *min_out = lmin;
642  *max_out = lmax;
643  return true;
644 }
645 
646 AclMethod AclMethodFromString(const char *string)
647 {
648  static const char *const ACL_METHOD_TYPES[] =
649  { "append", "overwrite", NULL };
650 
651  return FindTypeInArray(ACL_METHOD_TYPES, string, ACL_METHOD_NONE, ACL_METHOD_NONE);
652 }
653 
654 AclType AclTypeFromString(const char *string)
655 {
656  static const char *const ACL_TYPES[]=
657  { "generic", "posix", "ntfs", NULL };
658 
659  return FindTypeInArray(ACL_TYPES, string, ACL_TYPE_NONE, ACL_TYPE_NONE);
660 }
661 
662 /* For the deprecated attribute acl_directory_inherit. */
664 {
665  static const char *const ACL_INHERIT_TYPES[5] =
666  { "nochange", "specify", "parent", "clear", NULL };
667 
668  return FindTypeInArray(ACL_INHERIT_TYPES, string, ACL_DEFAULT_NONE, ACL_DEFAULT_NONE);
669 }
670 
671 AclDefault AclDefaultFromString(const char *string)
672 {
673  static const char *const ACL_DEFAULT_TYPES[5] =
674  { "nochange", "specify", "access", "clear", NULL };
675 
676  return FindTypeInArray(ACL_DEFAULT_TYPES, string, ACL_DEFAULT_NONE, ACL_DEFAULT_NONE);
677 }
678 
679 AclInherit AclInheritFromString(const char *string)
680 {
681  char *start, *end;
682  char *options = CF_BOOL ",nochange";
683  int i;
684  int size;
685 
686  if (string == NULL)
687  {
688  return ACL_INHERIT_NOCHANGE;
689  }
690 
691  start = options;
692  size = strlen(string);
693  for (i = 0;; i++)
694  {
695  end = strchr(start, ',');
696  if (end == NULL)
697  {
698  break;
699  }
700  if (size == end - start && strncmp(string, start, end - start) == 0)
701  {
702  // Even i is true, odd i is false (from CF_BOOL).
703  return (i & 1) ? ACL_INHERIT_FALSE : ACL_INHERIT_TRUE;
704  }
705  start = end + 1;
706  }
707  return ACL_INHERIT_NOCHANGE;
708 }
709 
710 const char *DataTypeShortToType(char *short_type)
711 {
712  assert(short_type);
713 
714  if(strcmp(short_type, "s") == 0)
715  {
716  return "string";
717  }
718 
719  if(strcmp(short_type, "i") == 0)
720  {
721  return "int";
722  }
723 
724  if(strcmp(short_type, "r") == 0)
725  {
726  return "real";
727  }
728 
729  if(strcmp(short_type, "m") == 0)
730  {
731  return "menu";
732  }
733 
734  if(strcmp(short_type, "sl") == 0)
735  {
736  return "string list";
737  }
738 
739  if(strcmp(short_type, "il") == 0)
740  {
741  return "int list";
742  }
743 
744  if(strcmp(short_type, "rl") == 0)
745  {
746  return "real list";
747  }
748 
749  if(strcmp(short_type, "ml") == 0)
750  {
751  return "menu list";
752  }
753 
754  return "unknown type";
755 }
756 
758 {
759  if (t == CF_DATA_TYPE_STRING_LIST ||
760  t == CF_DATA_TYPE_INT_LIST ||
761  t == CF_DATA_TYPE_REAL_LIST ||
763  {
764  return true;
765  }
766  else
767  {
768  return false;
769  }
770 }
771 
772 bool CoarseLaterThan(const char *bigger, const char *smaller)
773 {
774  char month_small[CF_SMALLBUF];
775  char month_big[CF_SMALLBUF];
776  int m_small, day_small, year_small, m_big, year_big, day_big;
777 
778  sscanf(smaller, "%d %s %d", &day_small, month_small, &year_small);
779  sscanf(bigger, "%d %s %d", &day_big, month_big, &year_big);
780 
781  if (year_big < year_small)
782  {
783  return false;
784  }
785 
786  m_small = Month2Int(month_small);
787  m_big = Month2Int(month_big);
788 
789  if (m_big < m_small)
790  {
791  return false;
792  }
793 
794  if (day_big < day_small && m_big == m_small && year_big == year_small)
795  {
796  return false;
797  }
798 
799  return true;
800 }
801 
802 int Month2Int(const char *string)
803 {
804  int i;
805 
806  if (string == NULL)
807  {
808  return -1;
809  }
810 
811  for (i = 0; i < 12; i++)
812  {
813  if (strncmp(MONTH_TEXT[i], string, strlen(string)) == 0)
814  {
815  return i + 1;
816  break;
817  }
818  }
819 
820  return -1;
821 }
822 
823 /*********************************************************************/
824 
825 void TimeToDateStr(time_t t, char *outStr, int outStrSz)
826 /**
827  * Formats a time as "30 Sep 2010".
828  */
829 {
830  char month[CF_SMALLBUF], day[CF_SMALLBUF], year[CF_SMALLBUF];
831  char tmp[CF_SMALLBUF];
832 
833  snprintf(tmp, sizeof(tmp), "%s", ctime(&t));
834  sscanf(tmp, "%*s %5s %3s %*s %5s", month, day, year);
835  snprintf(outStr, outStrSz, "%s %s %s", day, month, year);
836 }
837 
838 /*********************************************************************/
839 
840 /**
841  * Copy first argument of #src to #dst. Argument is delimited either by double
842  * quotes if first character is double quotes, or by space.
843  *
844  * @note Thread-safe version of CommandArg0().
845  *
846  * @return The length of #dst, or (size_t) -1 in case of overflow.
847  */
848 size_t CommandArg0_bound(char *dst, const char *src, size_t dst_size)
849 {
850  const char *start;
851  char end_delimiter;
852 
853  if(src[0] == '\"')
854  {
855  start = &src[1];
856  end_delimiter = '\"';
857  }
858  else
859  {
860  start = src;
861  end_delimiter = ' ';
862  }
863 
864  char *end = strchrnul(start, end_delimiter);
865  size_t len = end - start;
866  if (len < dst_size)
867  {
868  memcpy(dst, start, len);
869  dst[len] = '\0';
870  return len;
871  }
872  else
873  {
874  /* Check return value of CommandArg0_bound! If -1, the user should
875  * never use dst, but just in case we are writing a bogus string. */
876  const char trap[] = "BUG: COMMANDARG0_TOO_LONG";
877  strlcpy(dst, trap, dst_size);
878  return (size_t) -1;
879  }
880 }
881 
882 const char *CommandArg0(const char *execstr)
883 /**
884  * WARNING: Not thread-safe.
885  **/
886 {
887  static char arg[CF_BUFSIZE]; /* GLOBAL_R, no initialization needed */
888 
889  const char *start;
890  char end_delimiter;
891 
892  if(execstr[0] == '\"')
893  {
894  start = execstr + 1;
895  end_delimiter = '\"';
896  }
897  else
898  {
899  start = execstr;
900  end_delimiter = ' ';
901  }
902 
903  strlcpy(arg, start, sizeof(arg));
904 
905  char *cut = strchr(arg, end_delimiter);
906 
907  if(cut)
908  {
909  *cut = '\0';
910  }
911 
912  return arg;
913 }
914 
915 /*************************************************************/
916 
917 void CommandPrefix(char *execstr, char *comm)
918 {
919  char *sp;
920 
921  for (sp = execstr; (*sp != ' ') && (*sp != '\0'); sp++)
922  {
923  }
924 
925  if (sp - 10 >= execstr)
926  {
927  sp -= 10; /* copy 15 most relevant characters of command */
928  }
929  else
930  {
931  sp = execstr;
932  }
933 
934  memset(comm, 0, 20);
935  strncpy(comm, sp, 15);
936 }
937 
938 /*******************************************************************/
939 
940 bool IsRealNumber(const char *s)
941 {
942  double d;
943  int ret = sscanf(s, "%lf", &d);
944 
945  if (ret != 1)
946  {
947  return false;
948  }
949 
950  return true;
951 }
952 
953 #ifndef __MINGW32__
954 
955 /*******************************************************************/
956 /* Unix-only functions */
957 /*******************************************************************/
958 
959 /****************************************************************************/
960 /* Rlist to Uid/Gid lists */
961 /****************************************************************************/
962 
964 {
965 
966  while (uids)
967  {
968  UidList *ulp = uids;
969  uids = uids->next;
970  free(ulp->uidname);
971  free(ulp);
972  }
973 }
974 
975 static void AddSimpleUidItem(UidList ** uidlist, uid_t uid, char *uidname)
976 {
977  UidList *ulp = xcalloc(1, sizeof(UidList));
978 
979  ulp->uid = uid;
980 
981  if (uid == CF_UNKNOWN_OWNER) /* unknown user */
982  {
983  ulp->uidname = xstrdup(uidname);
984  }
985 
986  if (*uidlist == NULL)
987  {
988  *uidlist = ulp;
989  }
990  else /* Hang new element off end of list: */
991  {
992  UidList *u = *uidlist;
993 
994  while (u->next != NULL)
995  {
996  u = u->next;
997  }
998  u->next = ulp;
999  }
1000 }
1001 
1002 UidList *Rlist2UidList(Rlist *uidnames, const Promise *pp)
1003 {
1004  UidList *uidlist = NULL;
1005  Rlist *rp;
1006  char username[CF_MAXVARSIZE];
1007  uid_t uid;
1008 
1009  for (rp = uidnames; rp != NULL; rp = rp->next)
1010  {
1011  username[0] = '\0';
1012  uid = Str2Uid(RlistScalarValue(rp), username, pp);
1013  AddSimpleUidItem(&uidlist, uid, username);
1014  }
1015 
1016  if (uidlist == NULL)
1017  {
1018  AddSimpleUidItem(&uidlist, CF_SAME_OWNER, NULL);
1019  }
1020 
1021  return uidlist;
1022 }
1023 
1024 /*********************************************************************/
1025 
1027 {
1028  while (gids)
1029  {
1030  GidList *glp = gids;
1031  gids = gids->next;
1032  free(glp->gidname);
1033  free(glp);
1034  }
1035 }
1036 
1037 static void AddSimpleGidItem(GidList ** gidlist, gid_t gid, char *gidname)
1038 {
1039  GidList *glp = xcalloc(1, sizeof(GidList));
1040 
1041  glp->gid = gid;
1042 
1043  if (gid == CF_UNKNOWN_GROUP) /* unknown group */
1044  {
1045  glp->gidname = xstrdup(gidname);
1046  }
1047 
1048  if (*gidlist == NULL)
1049  {
1050  *gidlist = glp;
1051  }
1052  else /* Hang new element off end of list: */
1053  {
1054  GidList *g = *gidlist;
1055  while (g->next != NULL)
1056  {
1057  g = g->next;
1058  }
1059  g->next = glp;
1060  }
1061 }
1062 
1063 GidList *Rlist2GidList(Rlist *gidnames, const Promise *pp)
1064 {
1065  GidList *gidlist = NULL;
1066  Rlist *rp;
1067  char groupname[CF_MAXVARSIZE];
1068  gid_t gid;
1069 
1070  for (rp = gidnames; rp != NULL; rp = rp->next)
1071  {
1072  groupname[0] = '\0';
1073  gid = Str2Gid(RlistScalarValue(rp), groupname, pp);
1074  AddSimpleGidItem(&gidlist, gid, groupname);
1075  }
1076 
1077  if (gidlist == NULL)
1078  {
1079  AddSimpleGidItem(&gidlist, CF_SAME_GROUP, NULL);
1080  }
1081 
1082  return gidlist;
1083 }
1084 
1085 /*********************************************************************/
1086 
1087 uid_t Str2Uid(const char *uidbuff, char *usercopy, const Promise *pp)
1088 {
1089  Item *ip, *tmplist;
1090  struct passwd *pw;
1091  int offset, uid = -2, tmp = -2;
1092  char *machine, *user, *domain;
1093 
1094  if (uidbuff[0] == '+') /* NIS group - have to do this in a roundabout */
1095  { /* way because calling getpwnam spoils getnetgrent */
1096  offset = 1;
1097  if (uidbuff[1] == '@')
1098  {
1099  offset++;
1100  }
1101 
1102  setnetgrent(uidbuff + offset);
1103  tmplist = NULL;
1104 
1105  while (getnetgrent(&machine, &user, &domain))
1106  {
1107  if (user != NULL)
1108  {
1109  AppendItem(&tmplist, user, NULL);
1110  }
1111  }
1112 
1113  endnetgrent();
1114 
1115  for (ip = tmplist; ip != NULL; ip = ip->next)
1116  {
1117  if ((pw = getpwnam(ip->name)) == NULL)
1118  {
1119  Log(LOG_LEVEL_INFO, "Unknown user in promise '%s'", ip->name);
1120 
1121  if (pp != NULL)
1122  {
1124  }
1125 
1126  uid = CF_UNKNOWN_OWNER; /* signal user not found */
1127  }
1128  else
1129  {
1130  uid = pw->pw_uid;
1131 
1132  if (usercopy != NULL)
1133  {
1134  strcpy(usercopy, ip->name);
1135  }
1136  }
1137  }
1138 
1139  DeleteItemList(tmplist);
1140  return uid;
1141  }
1142 
1143  if (StringIsNumeric(uidbuff))
1144  {
1145  sscanf(uidbuff, "%d", &tmp);
1146  uid = (uid_t) tmp;
1147  }
1148  else
1149  {
1150  if (strcmp(uidbuff, "*") == 0)
1151  {
1152  uid = CF_SAME_OWNER; /* signals wildcard */
1153  }
1154  else if ((pw = getpwnam(uidbuff)) == NULL)
1155  {
1156  Log(LOG_LEVEL_INFO, "Unknown user '%s' in promise", uidbuff);
1157  uid = CF_UNKNOWN_OWNER; /* signal user not found */
1158 
1159  if (usercopy != NULL)
1160  {
1161  strcpy(usercopy, uidbuff);
1162  }
1163  }
1164  else
1165  {
1166  uid = pw->pw_uid;
1167  }
1168  }
1169 
1170  return uid;
1171 }
1172 
1173 /*********************************************************************/
1174 
1175 gid_t Str2Gid(const char *gidbuff, char *groupcopy, const Promise *pp)
1176 {
1177  struct group *gr;
1178  int gid = -2, tmp = -2;
1179 
1180  if (StringIsNumeric(gidbuff))
1181  {
1182  sscanf(gidbuff, "%d", &tmp);
1183  gid = (gid_t) tmp;
1184  }
1185  else
1186  {
1187  if (strcmp(gidbuff, "*") == 0)
1188  {
1189  gid = CF_SAME_GROUP; /* signals wildcard */
1190  }
1191  else if ((gr = getgrnam(gidbuff)) == NULL)
1192  {
1193  Log(LOG_LEVEL_INFO, "Unknown group '%s' in promise", gidbuff);
1194 
1195  if (pp)
1196  {
1198  }
1199 
1200  gid = CF_UNKNOWN_GROUP;
1201  }
1202  else
1203  {
1204  gid = gr->gr_gid;
1205 
1206  if (groupcopy != NULL)
1207  {
1208  strcpy(groupcopy, gidbuff);
1209  }
1210  }
1211  }
1212 
1213  return gid;
1214 }
1215 
1216 #else /* !__MINGW32__ */
1217 
1218 /* Release everything NovaWin_Rlist2SidList() allocates: */
1219 void UidListDestroy(UidList *uids)
1220 {
1221  while (uids)
1222  {
1223  UidList *ulp = uids;
1224  uids = uids->next;
1225  free(ulp);
1226  }
1227 }
1228 
1229 void GidListDestroy(ARG_UNUSED GidList *gids)
1230 {
1231  assert(gids == NULL);
1232 }
1233 
1234 #endif
void * xcalloc(size_t nmemb, size_t size)
Definition: alloc-mini.c:51
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
#define ARG_UNUSED
Definition: cf-net.c:47
@ cfa_usr2
Definition: cf3.defs.h:766
@ cfa_quit
Definition: cf3.defs.h:762
@ cfa_term
Definition: cf3.defs.h:763
@ cfa_child
Definition: cf3.defs.h:764
@ cfa_pipe
Definition: cf3.defs.h:758
@ cfa_kill
Definition: cf3.defs.h:757
@ cfa_segv
Definition: cf3.defs.h:768
@ cfa_bus
Definition: cf3.defs.h:767
@ cfa_hup
Definition: cf3.defs.h:754
@ cfa_abrt
Definition: cf3.defs.h:760
@ cfa_int
Definition: cf3.defs.h:755
@ cfa_usr1
Definition: cf3.defs.h:765
@ cfa_stop
Definition: cf3.defs.h:761
@ cfa_cont
Definition: cf3.defs.h:759
@ cfa_trap
Definition: cf3.defs.h:756
MeasurePolicy
Definition: cf3.defs.h:1395
@ MEASURE_POLICY_NONE
Definition: cf3.defs.h:1400
@ MEASURE_POLICY_AVERAGE
Definition: cf3.defs.h:1396
FileComparator
Definition: cf3.defs.h:696
@ FILE_COMPARATOR_NONE
Definition: cf3.defs.h:704
#define CF_HIGHINIT
Definition: cf3.defs.h:551
PackageVersionComparator
Definition: cf3.defs.h:791
@ PACKAGE_VERSION_COMPARATOR_NONE
Definition: cf3.defs.h:798
NewPackageAction
Definition: cf3.defs.h:784
@ NEW_PACKAGE_ACTION_NONE
Definition: cf3.defs.h:787
#define CF_BOOL
Definition: cf3.defs.h:555
Interval
Definition: cf3.defs.h:689
@ INTERVAL_NONE
Definition: cf3.defs.h:692
PackageAction
Definition: cf3.defs.h:772
@ PACKAGE_ACTION_NONE
Definition: cf3.defs.h:780
#define CF_SIGNALRANGE
Definition: cf3.defs.h:554
DatabaseType
Definition: cf3.defs.h:974
@ DATABASE_TYPE_NONE
Definition: cf3.defs.h:977
AclMethod
Definition: cf3.defs.h:827
@ ACL_METHOD_NONE
Definition: cf3.defs.h:830
ShellType
Definition: cf3.defs.h:1105
@ SHELL_TYPE_USE
Definition: cf3.defs.h:1107
@ SHELL_TYPE_NONE
Definition: cf3.defs.h:1106
@ SHELL_TYPE_POWERSHELL
Definition: cf3.defs.h:1108
#define CF_UNKNOWN_GROUP
Definition: cf3.defs.h:65
#define CF_SAME_OWNER
Definition: cf3.defs.h:62
PackageActionPolicy
Definition: cf3.defs.h:802
@ PACKAGE_ACTION_POLICY_NONE
Definition: cf3.defs.h:805
InsertMatchType
Definition: cf3.defs.h:877
@ INSERT_MATCH_TYPE_EXACT
Definition: cf3.defs.h:881
AclDefault
Definition: cf3.defs.h:842
@ ACL_DEFAULT_NONE
Definition: cf3.defs.h:847
AclInherit
Definition: cf3.defs.h:851
@ ACL_INHERIT_FALSE
Definition: cf3.defs.h:852
@ ACL_INHERIT_NOCHANGE
Definition: cf3.defs.h:854
@ ACL_INHERIT_TRUE
Definition: cf3.defs.h:853
#define CF_SAME_GROUP
Definition: cf3.defs.h:64
DataType
Definition: cf3.defs.h:368
@ CF_DATA_TYPE_CONTEXT_LIST
Definition: cf3.defs.h:380
@ CF_DATA_TYPE_CONTEXT
Definition: cf3.defs.h:379
@ CF_DATA_TYPE_OPTION_LIST
Definition: cf3.defs.h:376
@ CF_DATA_TYPE_BUNDLE
Definition: cf3.defs.h:378
@ CF_DATA_TYPE_NONE
Definition: cf3.defs.h:385
@ CF_DATA_TYPE_REAL
Definition: cf3.defs.h:371
@ CF_DATA_TYPE_STRING_LIST
Definition: cf3.defs.h:372
@ CF_DATA_TYPE_INT_LIST
Definition: cf3.defs.h:373
@ CF_DATA_TYPE_STRING
Definition: cf3.defs.h:369
@ CF_DATA_TYPE_INT
Definition: cf3.defs.h:370
@ CF_DATA_TYPE_BODY
Definition: cf3.defs.h:377
@ CF_DATA_TYPE_OPTION
Definition: cf3.defs.h:375
@ CF_DATA_TYPE_COUNTER
Definition: cf3.defs.h:383
@ CF_DATA_TYPE_INT_RANGE
Definition: cf3.defs.h:381
@ CF_DATA_TYPE_CONTAINER
Definition: cf3.defs.h:384
@ CF_DATA_TYPE_REAL_RANGE
Definition: cf3.defs.h:382
@ CF_DATA_TYPE_REAL_LIST
Definition: cf3.defs.h:374
ContextScope
Definition: cf3.defs.h:945
@ CONTEXT_SCOPE_NAMESPACE
Definition: cf3.defs.h:946
@ CONTEXT_SCOPE_NONE
Definition: cf3.defs.h:948
PasswordFormat
Definition: cf3.defs.h:1441
@ PASSWORD_FORMAT_NONE
Definition: cf3.defs.h:1444
EnvironmentState
Definition: cf3.defs.h:1477
@ ENVIRONMENT_STATE_NONE
Definition: cf3.defs.h:1483
@ ENVIRONMENT_STATE_CREATE
Definition: cf3.defs.h:1478
AclType
Definition: cf3.defs.h:834
@ ACL_TYPE_NONE
Definition: cf3.defs.h:838
#define CF_INFINITY
Definition: cf3.defs.h:66
#define CF_LOWINIT
Definition: cf3.defs.h:552
FileLinkType
Definition: cf3.defs.h:708
@ FILE_LINK_TYPE_SYMLINK
Definition: cf3.defs.h:709
UserState
Definition: cf3.defs.h:1433
@ USER_STATE_NONE
Definition: cf3.defs.h:1437
#define CF_NOINT
Definition: cf3.defs.h:339
#define CF_UNKNOWN_OWNER
Definition: cf3.defs.h:63
time_t CFSTARTTIME
Definition: cf3globals.c:99
const char *const MONTH_TEXT[]
Definition: constants.c:39
void free(void *)
FileComparator FileComparatorFromString(const char *s)
Definition: conversion.c:289
AclInherit AclInheritFromString(const char *string)
Definition: conversion.c:679
ShellType ShellTypeFromString(const char *string)
Definition: conversion.c:103
GidList * Rlist2GidList(Rlist *gidnames, const Promise *pp)
Definition: conversion.c:1063
AclType AclTypeFromString(const char *string)
Definition: conversion.c:654
PackageAction PackageActionFromString(const char *s)
Definition: conversion.c:170
static void AddSimpleUidItem(UidList **uidlist, uid_t uid, char *uidname)
Definition: conversion.c:975
const char * CommandArg0(const char *execstr)
Definition: conversion.c:882
uid_t Str2Uid(const char *uidbuff, char *usercopy, const Promise *pp)
Definition: conversion.c:1087
int FindTypeInArray(const char *const haystack[], const char *needle, int default_value, int null_value)
Definition: conversion.c:51
Interval IntervalFromString(const char *string)
Definition: conversion.c:514
DataType DataTypeFromString(const char *name)
Definition: conversion.c:318
bool DoubleFromString(const char *s, double *value_out)
Definition: conversion.c:521
DatabaseType DatabaseTypeFromString(const char *s)
Definition: conversion.c:148
const char * MapAddress(const char *unspec_address)
Definition: conversion.c:38
bool CoarseLaterThan(const char *bigger, const char *smaller)
Definition: conversion.c:772
EnvironmentState EnvironmentStateFromString(const char *s)
Definition: conversion.c:77
size_t CommandArg0_bound(char *dst, const char *src, size_t dst_size)
Definition: conversion.c:848
UserState UserStateFromString(const char *s)
Definition: conversion.c:155
PasswordFormat PasswordFormatFromString(const char *s)
Definition: conversion.c:163
void GidListDestroy(GidList *gids)
Definition: conversion.c:1026
char * Rlist2String(Rlist *list, char *sep)
Definition: conversion.c:202
FileLinkType FileLinkTypeFromString(const char *s)
Definition: conversion.c:281
bool DataTypeIsIterable(DataType t)
Definition: conversion.c:757
AclDefault AclInheritanceFromString(const char *string)
Definition: conversion.c:663
PackageActionPolicy PackageActionPolicyFromString(const char *s)
Definition: conversion.c:192
long IntFromString(const char *s)
Definition: conversion.c:390
int Month2Int(const char *string)
Definition: conversion.c:802
AclDefault AclDefaultFromString(const char *string)
Definition: conversion.c:671
PackageVersionComparator PackageVersionComparatorFromString(const char *s)
Definition: conversion.c:184
int SignalFromString(const char *s)
Definition: conversion.c:221
static void AddSimpleGidItem(GidList **gidlist, gid_t gid, char *gidname)
Definition: conversion.c:1037
void TimeToDateStr(time_t t, char *outStr, int outStrSz)
Definition: conversion.c:825
gid_t Str2Gid(const char *gidbuff, char *groupcopy, const Promise *pp)
Definition: conversion.c:1175
ContextScope ContextScopeFromString(const char *scope_str)
Definition: conversion.c:275
const char * DataTypeToString(DataType type)
Definition: conversion.c:331
bool BooleanFromString(const char *s)
Definition: conversion.c:354
int SyslogPriorityFromString(const char *s)
Definition: conversion.c:94
bool IsRealNumber(const char *s)
Definition: conversion.c:940
NewPackageAction GetNewPackagePolicy(const char *s, const char **action_types)
Definition: conversion.c:179
DataType ConstraintSyntaxGetDataType(const ConstraintSyntax *body_syntax, const char *lval)
Definition: conversion.c:337
void CommandPrefix(char *execstr, char *comm)
Definition: conversion.c:917
static const char *const datatype_strings[]
Definition: conversion.c:297
UidList * Rlist2UidList(Rlist *uidnames, const Promise *pp)
Definition: conversion.c:1002
bool IntegerRangeFromString(const char *intrange, long *min_out, long *max_out)
Definition: conversion.c:607
InsertMatchType InsertMatchTypeFromString(const char *s)
Definition: conversion.c:85
const char * DataTypeShortToType(char *short_type)
Definition: conversion.c:710
MeasurePolicy MeasurePolicyFromString(const char *s)
Definition: conversion.c:69
AclMethod AclMethodFromString(const char *string)
Definition: conversion.c:646
void UidListDestroy(UidList *uids)
Definition: conversion.c:963
#define CF_BUFSIZE
Definition: definitions.h:50
#define CF_MAXVARSIZE
Definition: definitions.h:36
#define CF_SMALLBUF
Definition: definitions.h:49
#define NULL
Definition: getopt1.c:56
void AppendItem(Item **liststart, const char *itemstring, const char *classes)
Definition: item_lib.c:415
Item * SplitString(const char *string, char sep)
Definition: item_lib.c:546
void DeleteItemList(Item *item)
Definition: item_lib.c:808
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
@ LOG_LEVEL_INFO
Definition: logging.h:45
int getnetgrent(char **host, char **user, char **domain)
Definition: patches.c:60
void setnetgrent(const char *netgroup)
Definition: patches.c:47
void endnetgrent(void)
Definition: patches.c:78
void PromiseRef(LogLevel level, const Promise *pp)
Definition: promises.c:769
char * RlistScalarValue(const Rlist *rlist)
Definition: rlist.c:83
void RvalWrite(Writer *writer, Rval rval)
Definition: rlist.c:1386
char * strchrnul(const char *s, int c)
Definition: strchrnul.c:9
bool StringIsNumeric(const char *s)
Definition: string_lib.c:428
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:34
const char * lval
Definition: cf3.defs.h:656
const DataType dtype
Definition: cf3.defs.h:657
char * gidname
Definition: cf3.defs.h:330
GidList * next
Definition: cf3.defs.h:331
gid_t gid
Definition: cf3.defs.h:329
Definition: item_lib.h:33
Item * next
Definition: item_lib.h:38
char * name
Definition: item_lib.h:34
Definition: rlist.h:35
Rlist * next
Definition: rlist.h:37
UidList * next
Definition: cf3.defs.h:319
char * uidname
Definition: cf3.defs.h:318
uid_t uid
Definition: cf3.defs.h:317
Definition: writer.c:45
size_t WriterWrite(Writer *writer, const char *str)
Definition: writer.c:193
char * StringWriterClose(Writer *writer)
Definition: writer.c:262
Writer * StringWriter(void)
Definition: writer.c:67