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)  

writer.c
Go to the documentation of this file.
1 /*
2  Copyright 2020 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 <platform.h>
26 #include <writer.h>
27 
28 #include <misc_lib.h>
29 #include <alloc.h>
30 
31 typedef enum
32 {
35 } WriterType;
36 
37 typedef struct
38 {
39  char *data;
40  size_t len; /* Does not include trailing zero */
41  size_t allocated; /* Includes trailing zero */
43 
44 struct Writer_
45 {
47  union
48  {
50  FILE *file;
51  };
52 };
53 
54 /*********************************************************************/
55 
56 Writer *FileWriter(FILE *file)
57 {
58  Writer *writer = xcalloc(1, sizeof(Writer));
59 
60  writer->type = WT_FILE;
61  writer->file = file;
62  return writer;
63 }
64 
65 /*********************************************************************/
66 
68 {
69  Writer *writer = xcalloc(1, sizeof(Writer));
70 
71  writer->type = WT_STRING;
72  writer->string.data = xstrdup("");
73  writer->string.allocated = 1;
74  writer->string.len = 0;
75  return writer;
76 }
77 
78 /*********************************************************************/
79 
80 static void StringWriterReallocate(Writer *writer, size_t extra_length)
81 {
82  assert(writer != NULL);
83  writer->string.allocated = MAX(writer->string.allocated * 2, writer->string.len + extra_length + 1);
84  writer->string.data = xrealloc(writer->string.data, writer->string.allocated);
85 }
86 
87 static size_t StringWriterWriteChar(Writer *writer, char c)
88 {
89  assert(writer != NULL);
90  if (writer->string.len + 2 > writer->string.allocated)
91  {
92  StringWriterReallocate(writer, 2);
93  }
94 
95  writer->string.data[writer->string.len] = c;
96  writer->string.data[writer->string.len + 1] = '\0';
97  writer->string.len++;
98 
99  return 1;
100 }
101 
102 static size_t StringWriterWriteLen(Writer *writer, const char *str, size_t len_)
103 {
104  assert(writer != NULL);
105  /* NB: str[:len_] may come from read(), which hasn't '\0'-terminated */
106  size_t len = strnlen(str, len_);
107 
108  if (writer->string.len + len + 1 > writer->string.allocated)
109  {
110  StringWriterReallocate(writer, len);
111  }
112 
113  memcpy(writer->string.data + writer->string.len, str, len);
114  writer->string.data[writer->string.len + len] = '\0';
115  writer->string.len += len;
116 
117  return len;
118 }
119 
120 /*********************************************************************/
121 
122 static size_t FileWriterWriteF(Writer *writer, const char *fmt, va_list ap)
123 {
124  assert(writer != NULL);
125  return vfprintf(writer->file, fmt, ap);
126 }
127 
128 /*********************************************************************/
129 
130 static size_t FileWriterWriteLen(Writer *writer, const char *str, size_t len_)
131 {
132  assert(writer != NULL);
133  size_t len = strnlen(str, len_);
134 
135 #ifdef CFENGINE_TEST
136  return CFENGINE_TEST_fwrite(str, 1, len, writer->file);
137 #else
138  return fwrite(str, 1, len, writer->file);
139 #endif
140 }
141 
142 /*********************************************************************/
143 
144 size_t WriterWriteF(Writer *writer, const char *fmt, ...)
145 {
146  va_list ap;
147 
148  va_start(ap, fmt);
149  size_t size = WriterWriteVF(writer, fmt, ap);
150 
151  va_end(ap);
152  return size;
153 }
154 
155 /*********************************************************************/
156 
157 size_t WriterWriteVF(Writer *writer, const char *fmt, va_list ap)
158 {
159  assert(writer != NULL);
160  if (writer->type == WT_STRING)
161  {
162  char *str = NULL;
163 
164  xvasprintf(&str, fmt, ap);
165  size_t size = StringWriterWriteLen(writer, str, INT_MAX);
166 
167  free(str);
168  return size;
169  }
170  else
171  {
172  return FileWriterWriteF(writer, fmt, ap);
173  }
174 }
175 
176 /*********************************************************************/
177 
178 size_t WriterWriteLen(Writer *writer, const char *str, size_t len)
179 {
180  assert(writer != NULL);
181  if (writer->type == WT_STRING)
182  {
183  return StringWriterWriteLen(writer, str, len);
184  }
185  else
186  {
187  return FileWriterWriteLen(writer, str, len);
188  }
189 }
190 
191 /*********************************************************************/
192 
193 size_t WriterWrite(Writer *writer, const char *str)
194 {
195  return WriterWriteLen(writer, str, INT_MAX);
196 }
197 
198 /*********************************************************************/
199 
200 size_t WriterWriteChar(Writer *writer, char c)
201 {
202  assert(writer != NULL);
203  if (writer->type == WT_STRING)
204  {
205  return StringWriterWriteChar(writer, c);
206  }
207  else
208  {
209  char s[2] = { c, '\0' };
210  return FileWriterWriteLen(writer, s, 1);
211  }
212 }
213 
214 /*********************************************************************/
215 
216 size_t StringWriterLength(const Writer *writer)
217 {
218  assert(writer != NULL);
219  if (writer->type != WT_STRING)
220  {
221  ProgrammingError("Wrong writer type");
222  }
223 
224  return writer->string.len;
225 }
226 
227 /*********************************************************************/
228 
229 const char *StringWriterData(const Writer *writer)
230 {
231  assert(writer != NULL);
232  if (writer->type != WT_STRING)
233  {
234  ProgrammingError("Wrong writer type");
235  }
236 
237  return writer->string.data;
238 }
239 
240 /*********************************************************************/
241 
242 void WriterClose(Writer *writer)
243 {
244  assert(writer != NULL);
245  if (writer->type == WT_STRING)
246  {
247  free(writer->string.data);
248  }
249  else
250  {
251 #ifdef CFENGINE_TEST
252  CFENGINE_TEST_fclose(writer->file);
253 #else
254  fclose(writer->file);
255 #endif
256  }
257  free(writer);
258 }
259 
260 /*********************************************************************/
261 
262 char *StringWriterClose(Writer *writer)
263 // NOTE: transfer of ownership for allocated return value
264 {
265  assert(writer != NULL);
266 
267  if (writer->type != WT_STRING)
268  {
269  ProgrammingError("Wrong writer type");
270  }
271  char *data = writer->string.data;
272 
273  free(writer);
274  return data;
275 }
276 
277 FILE *FileWriterDetach(Writer *writer)
278 {
279  assert(writer != NULL);
280  if (writer->type != WT_FILE)
281  {
282  ProgrammingError("Wrong writer type");
283  }
284  FILE *file = writer->file;
285  free(writer);
286  return file;
287 }
288 
289 static void WriterWriteOptions(Writer *w, const struct option options[],
290  const char *const hints[])
291 {
292  WriterWriteF(w, "\nOptions:\n");
293  for (int i = 0; options[i].name != NULL; i++)
294  {
295  char short_option[] = ", -*";
296  if (options[i].val < 128)
297  {
298  // Within ASCII range, means there is a short option.
299  short_option[3] = options[i].val;
300  }
301  else
302  {
303  // No short option.
304  short_option[0] = '\0';
305  }
306  if (options[i].has_arg)
307  {
308  WriterWriteF(w, " --%-12s%s value - %s\n", options[i].name,
309  short_option, hints[i]);
310  }
311  else
312  {
313  WriterWriteF(w, " --%-12s%-10s - %s\n", options[i].name,
314  short_option, hints[i]);
315  }
316  }
317 }
318 
319 static void WriterWriteCommands(Writer *w, const Description *commands)
320 {
321  assert(commands != NULL);
322  WriterWriteF(w, "\nCommands:\n");
323  for (int i = 0; commands[i].name != NULL; i++)
324  {
325  WriterWriteF(w, " %-12s - %s.\n", commands[i].name,
326  commands[i].description);
327  WriterWriteF(w, " %-12s Usage: %s\n", "", commands[i].usage);
328  }
329 }
330 
331 void WriterWriteHelp(Writer *w, const char *component,
332  const struct option options[], const char *const hints[],
333  const Description *commands, bool command_first,
334  bool accepts_file_argument)
335 {
336  WriterWriteF(w, "Usage: %s%s [OPTIONS]%s%s\n", component,
337  (commands && command_first) ? " COMMAND" : "",
338  (commands && !command_first) ? " COMMAND" : "",
339  accepts_file_argument ? " [FILE]" : "");
340  if ((commands != NULL) && command_first)
341  {
342  WriterWriteCommands(w, commands);
343  }
344  WriterWriteOptions(w, options, hints);
345  if ((commands != NULL) && !command_first)
346  {
347  WriterWriteCommands(w, commands);
348  }
349  WriterWriteF(w, "\nWebsite: http://www.cfengine.com\n");
350  WriterWriteF(w, "This software is Copyright (C) "
351  "2008,2010-present Northern.tech AS.\n");
352 }
void * xcalloc(size_t nmemb, size_t size)
Definition: alloc-mini.c:51
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
int xvasprintf(char **strp, const char *fmt, va_list ap)
Definition: alloc.c:82
void * xrealloc(void *ptr, size_t size)
Definition: alloc.c:51
void usage()
Definition: cf-upgrade.c:40
void free(void *)
#define NULL
Definition: getopt1.c:56
#define ProgrammingError(...)
Definition: misc_lib.h:33
#define MAX(x, y)
Definition: snprintf.c:500
size_t strnlen(const char *str, size_t maxlen)
Definition: strnlen.c:32
const char * name
Definition: writer.h:69
size_t allocated
Definition: writer.c:41
size_t len
Definition: writer.c:40
char * data
Definition: writer.c:39
Definition: writer.c:45
StringWriterImpl string
Definition: writer.c:49
WriterType type
Definition: writer.c:46
FILE * file
Definition: writer.c:50
Definition: getopt.h:83
int val
Definition: getopt.h:93
char * name
Definition: getopt.h:87
void WriterWriteHelp(Writer *w, const char *component, const struct option options[], const char *const hints[], const Description *commands, bool command_first, bool accepts_file_argument)
Definition: writer.c:331
size_t StringWriterLength(const Writer *writer)
Definition: writer.c:216
size_t WriterWrite(Writer *writer, const char *str)
Definition: writer.c:193
Writer * FileWriter(FILE *file)
Definition: writer.c:56
static void WriterWriteOptions(Writer *w, const struct option options[], const char *const hints[])
Definition: writer.c:289
char * StringWriterClose(Writer *writer)
Definition: writer.c:262
const char * StringWriterData(const Writer *writer)
Definition: writer.c:229
size_t WriterWriteChar(Writer *writer, char c)
Definition: writer.c:200
size_t WriterWriteLen(Writer *writer, const char *str, size_t len)
Definition: writer.c:178
static size_t FileWriterWriteF(Writer *writer, const char *fmt, va_list ap)
Definition: writer.c:122
static size_t StringWriterWriteChar(Writer *writer, char c)
Definition: writer.c:87
static size_t FileWriterWriteLen(Writer *writer, const char *str, size_t len_)
Definition: writer.c:130
static void StringWriterReallocate(Writer *writer, size_t extra_length)
Definition: writer.c:80
size_t WriterWriteVF(Writer *writer, const char *fmt, va_list ap)
Definition: writer.c:157
static size_t StringWriterWriteLen(Writer *writer, const char *str, size_t len_)
Definition: writer.c:102
void WriterClose(Writer *writer)
Definition: writer.c:242
size_t WriterWriteF(Writer *writer, const char *fmt,...)
Definition: writer.c:144
WriterType
Definition: writer.c:32
@ WT_STRING
Definition: writer.c:33
@ WT_FILE
Definition: writer.c:34
static void WriterWriteCommands(Writer *w, const Description *commands)
Definition: writer.c:319
Writer * StringWriter(void)
Definition: writer.c:67
FILE * FileWriterDetach(Writer *writer)
Definition: writer.c:277