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)  

ornaments.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 #include <ornaments.h>
26 
27 #include <string_lib.h>
28 #include <rlist.h>
29 #include <logging.h>
30 #include <fncall.h>
31 #include <promises.h> /* PromiseID */
32 
33 
34 /**
35  * @brief Like StringAppend(), but replace characters '*' and '#' with their visible counterparts.
36  * @param buffer Buffer to be used.
37  * @param src Constant string to append
38  * @param n Total size of dst buffer. The string will be truncated if this is exceeded.
39  */
40 static bool StringAppendPromise(char *dst, const char *src, size_t n)
41 {
42  int i, j;
43  n--;
44  for (i = 0; i < n && dst[i]; i++)
45  {
46  }
47  for (j = 0; i < n && src[j]; i++, j++)
48  {
49  const char ch = src[j];
50  switch (ch)
51  {
52  case CF_MANGLED_NS:
53  dst[i] = ':';
54  break;
55 
56  case CF_MANGLED_SCOPE:
57  dst[i] = '.';
58  break;
59 
60  default:
61  dst[i] = ch;
62  break;
63  }
64  }
65  dst[i] = '\0';
66  return (i < n || !src[j]);
67 }
68 
69 /**
70  * @brief Like @c BufferAppendPromiseStr, but if @c str contains newlines
71  * and is longer than 2*N+3, then only copy an abbreviated version
72  * consisting of the first and last N characters, separated by @c `...`
73  * @param buffer Buffer to be used.
74  * @param str Constant string to append
75  * @param n Total size of dst buffer. The string will be truncated if this is exceeded.
76  * @param max_fragment Max. length of initial/final segment of @c str to keep
77  * @note 2*max_fragment+3 is the maximum length of the appended string (excl. terminating NULL)
78  *
79  */
80 static bool StringAppendAbbreviatedPromise(char *dst, const char *src, size_t n,
81  const size_t max_fragment)
82 {
83  /* check if `src` contains a new line (may happen for "insert_lines") */
84  const char *const nl = strchr(src, '\n');
85  if (nl == NULL)
86  {
87  return StringAppendPromise(dst, src, n);
88  }
89  else
90  {
91  /* `src` contains a newline: abbreviate it by taking the first and last few characters */
92  static const char sep[] = "...";
93  char abbr[sizeof(sep) + 2 * max_fragment];
94  const int head = (nl > src + max_fragment) ? max_fragment : (nl - src);
95  const char * last_line = strrchr(src, '\n') + 1;
96  assert(last_line); /* not max_fragmentULL, we know we have at least one '\n' */
97  const int tail = strlen(last_line);
98  if (tail > max_fragment)
99  {
100  last_line += tail - max_fragment;
101  }
102  memcpy(abbr, src, head);
103  strcpy(abbr + head, sep);
104  strcat(abbr, last_line);
105  return StringAppendPromise(dst, abbr, n);
106  }
107 }
108 
109 
110 /*********************************************************************/
111 
112 
113 void SpecialTypeBanner(TypeSequence type, int pass)
114 {
115  if (type == TYPE_SEQUENCE_CONTEXTS)
116  {
117  Log(LOG_LEVEL_VERBOSE, "C: .........................................................");
118  Log(LOG_LEVEL_VERBOSE, "C: BEGIN classes / conditions (pass %d)", pass);
119  }
120  if (type == TYPE_SEQUENCE_VARS)
121  {
122  Log(LOG_LEVEL_VERBOSE, "V: .........................................................");
123  Log(LOG_LEVEL_VERBOSE, "V: BEGIN variables (pass %d)", pass);
124  }
125 }
126 
127 void PromiseBanner(EvalContext *ctx, const Promise *pp)
128 {
129  char handle[CF_MAXVARSIZE];
130  const char *sp;
131 
132  if ((sp = PromiseGetHandle(pp)) || (sp = PromiseID(pp)))
133  {
134  strlcpy(handle, sp, CF_MAXVARSIZE);
135  }
136  else
137  {
138  strcpy(handle, "");
139  }
140 
141  Log(LOG_LEVEL_VERBOSE, "P: .........................................................");
142 
143  if (strlen(handle) > 0)
144  {
145  Log(LOG_LEVEL_VERBOSE, "P: BEGIN promise '%s' of type \"%s\" (pass %d)", handle, pp->parent_promise_type->name, EvalContextGetPass(ctx));
146  }
147  else
148  {
149  Log(LOG_LEVEL_VERBOSE, "P: BEGIN un-named promise of type \"%s\" (pass %d)", pp->parent_promise_type->name, EvalContextGetPass(ctx));
150  }
151 
152  const size_t n = 2*CF_MAXFRAGMENT + 3;
153  char pretty_promise_name[n+1];
154  pretty_promise_name[0] = '\0';
155  StringAppendAbbreviatedPromise(pretty_promise_name, pp->promiser, n, CF_MAXFRAGMENT);
156  Log(LOG_LEVEL_VERBOSE, "P: Promiser/affected object: '%s'", pretty_promise_name);
157 
158  Rlist *params = NULL;
159  char *varclass;
160  FnCall *fp;
161 
162  if ((params = EvalContextGetBundleArgs(ctx)))
163  {
164  Writer *w = StringWriter();
165  RlistWrite(w, params);
166  Log(LOG_LEVEL_VERBOSE, "P: From parameterized bundle: %s(%s)", PromiseGetBundle(pp)->name, StringWriterData(w));
167  WriterClose(w);
168  }
169  else
170  {
171  Log(LOG_LEVEL_VERBOSE, "P: Part of bundle: %s", PromiseGetBundle(pp)->name);
172  }
173 
174  Log(LOG_LEVEL_VERBOSE, "P: Base context class: %s", pp->classes);
175 
176  if ((varclass = PromiseGetConstraintAsRval(pp, "if", RVAL_TYPE_SCALAR)) || (varclass = PromiseGetConstraintAsRval(pp, "ifvarclass", RVAL_TYPE_SCALAR)))
177  {
178  Log(LOG_LEVEL_VERBOSE, "P: \"if\" class condition: %s", varclass);
179  }
180  else if ((fp = (FnCall *)PromiseGetConstraintAsRval(pp, "if", RVAL_TYPE_FNCALL)) || (fp = (FnCall *)PromiseGetConstraintAsRval(pp, "ifvarclass", RVAL_TYPE_FNCALL)))
181  {
182  Writer *w = StringWriter();
183  FnCallWrite(w, fp);
184  Log(LOG_LEVEL_VERBOSE, "P: \"if\" class condition: %s", StringWriterData(w));
185  }
186  else if ((varclass = PromiseGetConstraintAsRval(pp, "unless", RVAL_TYPE_SCALAR)))
187  {
188  Log(LOG_LEVEL_VERBOSE, "P: \"unless\" class condition: %s", varclass);
189  }
190  else if ((fp = (FnCall *)PromiseGetConstraintAsRval(pp, "unless", RVAL_TYPE_FNCALL)))
191  {
192  Writer *w = StringWriter();
193  FnCallWrite(w, fp);
194  Log(LOG_LEVEL_VERBOSE, "P: \"unless\" class condition: %s", StringWriterData(w));
195  }
196 
197  Log(LOG_LEVEL_VERBOSE, "P: Stack path: %s", EvalContextStackToString(ctx));
198 
199  if (pp->comment)
200  {
201  Log(LOG_LEVEL_VERBOSE, "P:\n");
202  Log(LOG_LEVEL_VERBOSE, "P: Comment: %s", pp->comment);
203  }
204 }
205 
206 void Legend()
207 {
208  Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------");
209  Log(LOG_LEVEL_VERBOSE, "PREFIX LEGEND:");
210  Log(LOG_LEVEL_VERBOSE, " V: variable or parameter new definition in scope");
211  Log(LOG_LEVEL_VERBOSE, " C: class/context new definition ");
212  Log(LOG_LEVEL_VERBOSE, " B: bundle start/end execution marker");
213  Log(LOG_LEVEL_VERBOSE, " P: promise execution output ");
214  Log(LOG_LEVEL_VERBOSE, " A: accounting output ");
215  Log(LOG_LEVEL_VERBOSE, " T: time measurement for stated object (promise or bundle)");
216  Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------");
217 }
218 
219 void Banner(const char *s)
220 {
221  Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------");
222  Log(LOG_LEVEL_VERBOSE, " %s ", s);
223  Log(LOG_LEVEL_VERBOSE, "----------------------------------------------------------------");
224 
225 }
226 
227 void BundleBanner(const Bundle *bp, const Rlist *params)
228 {
229  Log(LOG_LEVEL_VERBOSE, "B: *****************************************************************");
230 
231  if (params)
232  {
233  Writer *w = StringWriter();
234  RlistWrite(w, params);
235  Log(LOG_LEVEL_VERBOSE, "B: BEGIN bundle %s(%s)", bp->name, StringWriterData(w));
236  WriterClose(w);
237  }
238  else
239  {
240  Log(LOG_LEVEL_VERBOSE, "B: BEGIN bundle %s", bp->name);
241  }
242 
243  Log(LOG_LEVEL_VERBOSE, "B: *****************************************************************");
244 }
245 
246 void EndBundleBanner(const Bundle *bp)
247 {
248  if (bp == NULL)
249  {
250  return;
251  }
252 
253  Log(LOG_LEVEL_VERBOSE, "B: *****************************************************************");
254  Log(LOG_LEVEL_VERBOSE, "B: END bundle %s", bp->name);
255  Log(LOG_LEVEL_VERBOSE, "B: *****************************************************************");
256 }
#define CF_MAXFRAGMENT
Definition: cf3.defs.h:54
#define CF_MANGLED_SCOPE
Definition: cf3.defs.h:115
#define CF_MANGLED_NS
Definition: cf3.defs.h:114
TypeSequence
Definition: cf3.defs.h:521
@ TYPE_SEQUENCE_VARS
Definition: cf3.defs.h:523
@ TYPE_SEQUENCE_CONTEXTS
Definition: cf3.defs.h:525
@ RVAL_TYPE_SCALAR
Definition: cf3.defs.h:606
@ RVAL_TYPE_FNCALL
Definition: cf3.defs.h:608
#define CF_MAXVARSIZE
Definition: definitions.h:36
const char * EvalContextStackToString(EvalContext *ctx)
Definition: eval_context.c:371
Rlist * EvalContextGetBundleArgs(EvalContext *ctx)
int EvalContextGetPass(EvalContext *ctx)
void FnCallWrite(Writer *writer, const FnCall *call)
Definition: fncall.c:222
#define NULL
Definition: getopt1.c:56
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_VERBOSE
Definition: logging.h:46
void PromiseBanner(EvalContext *ctx, const Promise *pp)
Definition: ornaments.c:127
void BundleBanner(const Bundle *bp, const Rlist *params)
Definition: ornaments.c:227
void Banner(const char *s)
Definition: ornaments.c:219
void SpecialTypeBanner(TypeSequence type, int pass)
Definition: ornaments.c:113
void EndBundleBanner(const Bundle *bp)
Definition: ornaments.c:246
static bool StringAppendPromise(char *dst, const char *src, size_t n)
Like StringAppend(), but replace characters '*' and '#' with their visible counterparts.
Definition: ornaments.c:40
static bool StringAppendAbbreviatedPromise(char *dst, const char *src, size_t n, const size_t max_fragment)
Like BufferAppendPromiseStr, but if str contains newlines and is longer than 2*N+3,...
Definition: ornaments.c:80
void Legend()
Definition: ornaments.c:206
const char * PromiseGetHandle(const Promise *pp)
Return handle of the promise.
Definition: policy.c:2713
const Bundle * PromiseGetBundle(const Promise *pp)
Definition: policy.c:2671
void * PromiseGetConstraintAsRval(const Promise *pp, const char *lval, RvalType rtype)
Get the Rval value of the first effective constraint that matches the given type.
Definition: policy.c:3054
const char * PromiseID(const Promise *pp)
Definition: promises.c:814
void RlistWrite(Writer *writer, const Rlist *list)
Definition: rlist.c:1318
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:34
Definition: policy.h:70
char * name
Definition: policy.h:74
Definition: fncall.h:31
char * name
Definition: policy.h:103
PromiseType * parent_promise_type
Definition: policy.h:111
char * comment
Definition: policy.h:114
char * promiser
Definition: policy.h:115
char * classes
Definition: policy.h:113
Definition: rlist.h:35
Definition: writer.c:45
const char * StringWriterData(const Writer *writer)
Definition: writer.c:229
void WriterClose(Writer *writer)
Definition: writer.c:242
Writer * StringWriter(void)
Definition: writer.c:67