rpm  5.4.15
rpmaug.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #if defined(WITH_AUGEAS) && defined(HAVE_AUGEAS_H)
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 #include "augeas.h"
12 #ifdef __cplusplus
13 }
14 #endif
15 #endif
16 
17 #define _RPMIOB_INTERNAL
18 #include <rpmiotypes.h>
19 #include <rpmio.h> /* for *Pool methods */
20 #include <rpmlog.h>
21 #include <argv.h>
22 
23 #define _RPMAUG_INTERNAL
24 #include <rpmaug.h>
25 
26 #include "debug.h"
27 
28 #ifdef __cplusplus
29 GENfree(rpmioP)
30 #endif /* __cplusplus */
31 
32 /*@unchecked@*/
33 int _rpmaug_debug = 0;
34 
35 /*@unchecked@*/ /*@relnull@*/
37 
38 /*@-mustmod@*/ /* XXX splint on crack */
39 static void rpmaugFini(void * _aug)
40  /*@globals fileSystem @*/
41  /*@modifies *_aug, fileSystem @*/
42 {
43  rpmaug aug = (rpmaug) _aug;
44 
45 #if defined(WITH_AUGEAS)
46  augeas * I = (augeas *) aug->I;
47  (void) aug_close(I);
48 #endif
49  aug->I = NULL;
50  (void)rpmiobFree(aug->iob);
51  aug->iob = NULL;
52  aug->root = _free(aug->root);
53  aug->loadpath = _free(aug->loadpath);
54 }
55 /*@=mustmod@*/
56 
57 /*@unchecked@*/ /*@only@*/ /*@null@*/
59 
60 static rpmaug rpmaugGetPool(/*@null@*/ rpmioPool pool)
61  /*@globals _rpmaugPool, fileSystem @*/
62  /*@modifies pool, _rpmaugPool, fileSystem @*/
63 {
64  rpmaug aug;
65 
66  if (_rpmaugPool == NULL) {
67  _rpmaugPool = rpmioNewPool("aug", sizeof(*aug), -1, _rpmaug_debug,
68  NULL, NULL, rpmaugFini);
69  pool = _rpmaugPool;
70  }
71  return (rpmaug) rpmioGetPool(pool, sizeof(*aug));
72 }
73 
74 /*@unchecked@*/
75 static const char _root[] = "/";
76 const char * _rpmaugRoot = _root;
77 /*@unchecked@*/
78 static const char _loadpath[] = ""; /* XXX /usr/lib/rpm/lib ? */
79 const char * _rpmaugLoadpath = _loadpath;
80 unsigned int _rpmaugFlags = 0; /* AUG_NONE */
81 
82 #if defined(REFERENCE)
83 __attribute__((noreturn))
84 static void usage(void)
85 {
86  fprintf(stderr, "Usage: %s [OPTIONS] [COMMAND]\n", progname);
87  fprintf(stderr, "Load the Augeas tree and modify it. If no COMMAND is given, run interactively\n");
88  fprintf(stderr, "Run '%s help' to get a list of possible commands.\n",
89  progname);
90  fprintf(stderr, "\nOptions:\n\n");
91  fprintf(stderr, " -c, --typecheck typecheck lenses\n");
92  fprintf(stderr, " -b, --backup preserve originals of modified files with\n"
93  " extension '.augsave'\n");
94  fprintf(stderr, " -n, --new save changes in files with extension '.augnew',\n"
95  " leave original unchanged\n");
96  fprintf(stderr, " -r, --root ROOT use ROOT as the root of the filesystem\n");
97  fprintf(stderr, " -I, --include DIR search DIR for modules; can be given mutiple times\n");
98  fprintf(stderr, " --nostdinc do not search the builtin default directories for modules\n");
99  fprintf(stderr, " --noload do not load any files into the tree on startup\n");
100  fprintf(stderr, " --noautoload do not autoload modules from the search path\n");
101 
102  exit(EXIT_FAILURE);
103 }
104 #endif
105 
106 /*@unchecked@*/ /*@null@*/
107 const char ** _rpmaugLoadargv;
108 
109 struct poptOption rpmaugPoptTable[] = {
110 #if defined(WITH_AUGEAS)
111  /* XXX POPT_ARGFLAG_TOGGLE? */
112  { "typecheck",'c', POPT_BIT_SET, &_rpmaugFlags, AUG_TYPE_CHECK,
113  N_("Type check lenses"), NULL },
114  { "backup", 'b',POPT_BIT_SET, &_rpmaugFlags, AUG_SAVE_BACKUP,
115  N_("Backup modified files with suffix '.augsave'"), NULL },
116  { "new", 'n', POPT_BIT_SET, &_rpmaugFlags, AUG_SAVE_NEWFILE,
117  N_("Save modified files with suffix '.augnew'"), NULL },
118  { "root", 'r', POPT_ARG_STRING, &_rpmaugRoot, 0,
119  N_("Use ROOT as the root of the filesystem"), N_("ROOT") },
120  { "include", 'I', POPT_ARG_ARGV, &_rpmaugLoadargv, 0,
121  N_("Search DIR for modules (may be used more than once)"), N_("DIR") },
122  { "nostdinc", '\0', POPT_BIT_SET, &_rpmaugFlags, AUG_NO_STDINC,
123  N_("Do not search default modules path"), NULL },
124  { "noload", '\0', POPT_BIT_SET, &_rpmaugFlags, AUG_NO_LOAD,
125  N_("Do not load files into tree on startup"), NULL },
126  { "noautoload", '\0', POPT_BIT_SET, &_rpmaugFlags, AUG_NO_MODL_AUTOLOAD,
127  N_("Do not autoload modules from the search path"), NULL },
128 #endif
129  POPT_TABLEEND
130 };
131 
132 rpmaug rpmaugNew(const char * root, const char * loadpath, unsigned int flags)
133 {
134  rpmaug aug = rpmaugGetPool(_rpmaugPool);
135 
136  if (root == NULL || *root == '\0')
137  root = _rpmaugRoot;
138  if (root == NULL || *root == '\0')
139  root = "/";
140  if (loadpath == NULL)
141  loadpath = _rpmaugLoadpath;
142  aug->root = xstrdup(root);
143  aug->loadpath = xstrdup(loadpath);
144  aug->flags = flags;
145 #if defined(WITH_AUGEAS)
146  aug->I = (void *) aug_init(aug->root, aug->loadpath, aug->flags);
147 assert(aug->I != NULL);
148 #endif
149  aug->iob = rpmiobNew(0);
150 
151  return rpmaugLink(aug);
152 }
153 
154 #ifdef WITH_AUGEAS
155 static rpmaug rpmaugI(void)
156  /*@globals _rpmaugI @*/
157  /*@modifies _rpmaugI @*/
158 {
159  if (_rpmaugI == NULL)
160  _rpmaugI = rpmaugNew(_rpmaugRoot, _rpmaugLoadpath, _rpmaugFlags);
161  return _rpmaugI;
162 }
163 #endif
164 
165 int rpmaugDefvar(rpmaug aug, const char * name, const char * expr)
166 {
167  int rc = -1;
168 #ifdef WITH_AUGEAS
169  augeas * I;
170  if (aug == NULL) aug = rpmaugI();
171  I = (augeas *) aug->I;
172  rc = aug_defvar(I, name, expr);
173 #endif
174 if (_rpmaug_debug < 0)
175 fprintf(stderr, "<-- %s(%p,\"%s\",\"%s\") rc %d\n", __FUNCTION__, aug, name, expr, rc);
176  return rc;
177 }
178 
179 int rpmaugDefnode(rpmaug aug, const char * name, const char * expr,
180  const char * value, int * created)
181 {
182  int rc = -1;
183 #ifdef WITH_AUGEAS
184  augeas * I;
185  if (aug == NULL) aug = rpmaugI();
186  I = (augeas *) aug->I;
187  rc = aug_defnode(I, name, expr, value, created);
188 #endif
189 if (_rpmaug_debug < 0)
190 fprintf(stderr, "<-- %s(%p,\"%s\",\"%s\",\"%s\",%p) rc %d *created %d\n", __FUNCTION__, aug, name, expr, value, created, rc, (created ? *created : 0));
191  return rc;
192 }
193 
194 int rpmaugGet(rpmaug aug, const char * path, const char ** value)
195 {
196  int rc = -1;
197 #ifdef WITH_AUGEAS
198  augeas * I;
199  if (aug == NULL) aug = rpmaugI();
200  I = (augeas *) aug->I;
201  rc = aug_get(I, path, value);
202 #endif
203 if (_rpmaug_debug < 0)
204 fprintf(stderr, "<-- %s(%p,\"%s\",%p) rc %d *value \"%s\"\n", __FUNCTION__, aug, path, value, rc, (value ? *value : NULL));
205  return rc;
206 }
207 
208 int rpmaugSet(rpmaug aug, const char * path, const char * value)
209 {
210  int rc = -1;
211 #ifdef WITH_AUGEAS
212  augeas * I;
213  if (aug == NULL) aug = rpmaugI();
214  I = (augeas *) aug->I;
215  rc = aug_set(I, path, value);
216 #endif
217 if (_rpmaug_debug < 0)
218 fprintf(stderr, "<-- %s(%p,\"%s\",\"%s\") rc %d\n", __FUNCTION__, aug, path, value, rc);
219  return rc;
220 }
221 
222 int rpmaugInsert(rpmaug aug, const char * path, const char * label, int before)
223 {
224  int rc = -1;
225 #ifdef WITH_AUGEAS
226  augeas * I;
227  if (aug == NULL) aug = rpmaugI();
228  I = (augeas *) aug->I;
229  rc = aug_insert(I, path, label, before);
230 #endif
231 if (_rpmaug_debug < 0)
232 fprintf(stderr, "<-- %s(%p,\"%s\",\"%s\",%d) rc %d\n", __FUNCTION__, aug, path, label, before, rc);
233  return rc;
234 }
235 
236 int rpmaugRm(rpmaug aug, const char * path)
237 {
238  int rc = -1;
239 #ifdef WITH_AUGEAS
240  augeas * I;
241  if (aug == NULL) aug = rpmaugI();
242  I = (augeas *) aug->I;
243  rc = aug_rm(I, path);
244 #endif
245 if (_rpmaug_debug < 0)
246 fprintf(stderr, "<-- %s(%p,\"%s\") rc %d\n", __FUNCTION__, aug, path, rc);
247  return rc;
248 }
249 
250 int rpmaugMv(rpmaug aug, const char * src, const char * dst)
251 {
252  int rc = -1;
253 #ifdef WITH_AUGEAS
254  augeas * I;
255  if (aug == NULL) aug = rpmaugI();
256  I = (augeas *) aug->I;
257  rc = aug_mv(I, src, dst);
258 #endif
259 if (_rpmaug_debug < 0)
260 fprintf(stderr, "<-- %s(%p,\"%s\",\"%s\") rc %d\n", __FUNCTION__, aug, src, dst, rc);
261  return rc;
262 }
263 
264 int rpmaugMatch(rpmaug aug, const char * path, char *** matches)
265 {
266  int rc = -1;
267 #ifdef WITH_AUGEAS
268  augeas * I;
269  if (aug == NULL) aug = rpmaugI();
270  I = (augeas *) aug->I;
271  rc = aug_match(I, path, matches);
272 #endif
273 if (_rpmaug_debug < 0)
274 fprintf(stderr, "<-- %s(%p,\"%s\",%p) rc %d *matches %p\n", __FUNCTION__, aug, path, matches, rc, (matches ? *matches : NULL));
275  return rc;
276 }
277 
279 {
280  int rc = -1;
281 #ifdef WITH_AUGEAS
282  augeas * I;
283  if (aug == NULL) aug = rpmaugI();
284  I = (augeas *) aug->I;
285  rc = aug_save(I);
286 #endif
287 if (_rpmaug_debug < 0)
288 fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, aug, rc);
289  return rc;
290 }
291 
293 {
294  int rc = -1;
295 #ifdef WITH_AUGEAS
296  augeas * I;
297  if (aug == NULL) aug = rpmaugI();
298  I = (augeas *) aug->I;
299  rc = aug_load(I);
300 #endif
301 if (_rpmaug_debug < 0)
302 fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, aug, rc);
303  return rc;
304 }
305 
306 int rpmaugPrint(rpmaug aug, FILE *out, const char * path)
307 {
308  int rc = -1;
309 #ifdef WITH_AUGEAS
310  augeas * I;
311  if (aug == NULL) aug = rpmaugI();
312  I = (augeas *) aug->I;
313  if (out == NULL) out = stderr;
314  rc = aug_print(I, out, path);
315  (void) fflush(out);
316 #endif
317 if (_rpmaug_debug < 0)
318 fprintf(stderr, "<-- %s(%p, %p, \"%s\") rc %d\n", __FUNCTION__, aug, out, path, rc);
319  return rc;
320 }
321 
322 void rpmaugFprintf(rpmaug aug, const char *fmt, ...)
323 {
324 #if defined(WITH_AUGEAS)
325  size_t nb = 1024;
326  char * b = (char *) xmalloc(nb);
327  va_list va;
328 
329  va_start(va, fmt);
330  while(1) {
331  int nw = vsnprintf(b, nb, fmt, va);
332  if (nw > -1 && (size_t)nw < nb)
333  break;
334  if (nw > -1) /* glibc 2.1 (and later) */
335  nb = nw+1;
336  else /* glibc 2.0 */
337  nb *= 2;
338  b = (char *) xrealloc(b, nb);
339  }
340  va_end(va);
341 
342  if (aug == NULL) aug = rpmaugI();
343  (void) rpmiobAppend(aug->iob, b, 0);
344  b = _free(b);
345 #endif
346 }
347 
348 /* ===== internal.h */
349 
350 #if !defined(SEP)
351 #define SEP '/'
352 #endif
353 
354 #define DATADIR "/usr/share"
355 
356 /* Define: AUGEAS_LENS_DIR
357  * The default location for lens definitions */
358 #define AUGEAS_LENS_DIR DATADIR "/augeas/lenses"
359 
360 /* The directory where we install lenses distribute with Augeas */
361 #define AUGEAS_LENS_DIST_DIR DATADIR "/augeas/lenses/dist"
362 
363 /* Define: PATH_SEP_CHAR
364  * Character separating paths in a list of paths
365  */
366 #define PATH_SEP_CHAR ':'
367 
368 /* ===== */
369 
370 static char *cleanstr(char *path, const char sep)
371 {
372  if (path && *path) {
373  char *e = path + strlen(path) - 1;
374  while (e >= path && (*e == sep || xisspace(*e)))
375  *e-- = '\0';
376  }
377  return path;
378 }
379 
380 static char *cleanpath(char *path)
381 {
382  return cleanstr(path, SEP); /* XXX strip pesky trailing slashes */
383 }
384 
385 static void err_check(void)
386 {
387 #ifdef WITH_AUGEAS
388  rpmaug aug = rpmaugI();
389  augeas * I = (augeas *) aug->I;
390 
391  if (aug_error(I) != AUG_NOERROR) {
392  const char *minor = aug_error_minor_message(I);
393  const char *details = aug_error_details(I);
394 
395  fprintf(stderr, "error: %s\n", aug_error_message(I));
396  if (minor != NULL)
397  fprintf(stderr, "error: %s\n", minor);
398  if (details != NULL)
399  fprintf(stderr, "error: %s\n", details);
400  }
401 #endif
402 }
403 
404 static char *ls_pattern(const char *path)
405 {
406  char *q;
407  int r;
408 
409  if (path[strlen(path)-1] == SEP)
410  r = asprintf(&q, "%s*", path);
411  else
412  r = asprintf(&q, "%s/*", path);
413  if (r == -1)
414  return NULL;
415  return q;
416 }
417 
418 static int child_count(const char *path)
419 {
420  char *q = ls_pattern(path);
421  int cnt;
422 
423  if (q == NULL)
424  return 0;
425  cnt = rpmaugMatch(NULL, q, NULL);
426  err_check();
427  free(q);
428  return cnt;
429 }
430 
431 static int cmd_quit(int ac, char *av[])
432 {
433  return -1; /* XXX return immediately on quit and exit commands */
434 }
435 
436 static int cmd_ls(int ac, char *av[])
437 {
438  char *path = cleanpath(av[0]);
439  char **paths;
440  int cnt;
441  int i;
442 
443  path = ls_pattern(path);
444  if (path == NULL)
445  return -1;
446  cnt = rpmaugMatch(NULL, path, &paths);
447  err_check();
448  for (i = 0; i < cnt; i++) {
449  const char *basnam = strrchr(paths[i], SEP);
450  int dir = child_count(paths[i]);
451  const char *val;
452  rpmaugGet(NULL, paths[i], &val);
453  err_check();
454  basnam = (basnam == NULL) ? paths[i] : basnam + 1;
455  if (val == NULL)
456  val = "(none)";
457  rpmaugFprintf(NULL, "%s%s= %s\n", basnam, dir ? "/ " : " ", val);
458  paths[i] = _free(paths[i]);
459  }
460  if (cnt > 0)
461  paths = _free(paths);
462  path = _free(path);
463  return 0;
464 }
465 
466 static int cmd_match(int ac, char *av[])
467 {
468  const char *pattern = cleanpath(av[0]);
469  int filter = (av[1] != NULL) && (strlen(av[1]) > 0);
470  int result = 0;
471  char **matches = NULL;
472  int cnt;
473  int i;
474 
475  cnt = rpmaugMatch(NULL, pattern, &matches);
476  err_check();
477  if (cnt < 0) {
478  rpmaugFprintf(NULL, " (error matching %s)\n", pattern);
479  result = -1;
480  goto done;
481  }
482  if (cnt == 0) {
483  rpmaugFprintf(NULL, " (no matches)\n");
484  goto done;
485  }
486 
487  for (i = 0; i < cnt; i++) {
488  const char *val;
489  rpmaugGet(NULL, matches[i], &val);
490  err_check();
491  if (val == NULL)
492  val = "(none)";
493  if (filter) {
494  if (!strcmp(av[1], val))
495  rpmaugFprintf(NULL, "%s\n", matches[i]);
496  } else {
497  rpmaugFprintf(NULL, "%s = %s\n", matches[i], val);
498  }
499  }
500  done:
501  for (i = 0; i < cnt; i++)
502  matches[i] = _free(matches[i]);
503  matches = _free(matches);
504  return result;
505 }
506 
507 static int cmd_rm(int ac, char *av[])
508 {
509  const char *path = cleanpath(av[0]);
510  int cnt;
511 
512  rpmaugFprintf(NULL, "rm : %s", path);
513  cnt = rpmaugRm(NULL, path);
514  err_check();
515  rpmaugFprintf(NULL, " %d\n", cnt);
516  return 0;
517 }
518 
519 static int cmd_mv(int ac, char *av[])
520 {
521  const char *src = cleanpath(av[0]);
522  const char *dst = cleanpath(av[1]);
523  int r = rpmaugMv(NULL, src, dst);
524 
525  err_check();
526  if (r == -1)
527  rpmaugFprintf(NULL, "Failed\n");
528  return r;
529 }
530 
531 static int cmd_set(int ac, char *av[])
532 {
533  const char *path = cleanpath(av[0]);
534  const char *val = av[1];
535  int r = rpmaugSet(NULL, path, val);
536 
537  err_check();
538  if (r == -1)
539  rpmaugFprintf(NULL, "Failed\n");
540  return r;
541 }
542 
543 static int cmd_defvar(int ac, char *av[])
544 {
545  const char *name = av[0];
546  const char *path = (av[1] && *av[1] ? cleanpath(av[1]) : NULL);
547  int r = rpmaugDefvar(NULL, name, path);
548 
549  err_check();
550  if (r == -1)
551  rpmaugFprintf(NULL, "Failed\n");
552  return r;
553 }
554 
555 static int cmd_defnode(int ac, char *av[])
556 {
557  const char *name = av[0];
558  const char *path = cleanpath(av[1]);
559  const char *value = av[2];
560  int r;
561 
562  /* Our simple minded line parser treats non-existant and empty values
563  * the same. We choose to take the empty string to mean NULL */
564  if (value != NULL && value[0] == '\0')
565  value = NULL;
566 
567  r = rpmaugDefnode(NULL, name, path, value, NULL);
568  err_check();
569  if (r == -1)
570  rpmaugFprintf(NULL, "Failed\n");
571  return r;
572 }
573 
574 static int cmd_clear(int ac, char *av[])
575 {
576  const char *path = cleanpath(av[0]);
577  int r = rpmaugSet(NULL, path, NULL);
578 
579  err_check();
580  if (r == -1)
581  rpmaugFprintf(NULL, "Failed\n");
582  return r;
583 }
584 
585 static int cmd_get(int ac, char *av[])
586 {
587  const char *path = cleanpath(av[0]);
588  const char *val;
589 
590  rpmaugFprintf(NULL, "%s", path);
591  if (rpmaugGet(NULL, path, &val) != 1)
592  rpmaugFprintf(NULL, " (o)\n");
593  else if (val == NULL)
594  rpmaugFprintf(NULL, " (none)\n");
595  else
596  rpmaugFprintf(NULL, " = %s\n", val);
597  err_check();
598  return 0;
599 }
600 
601 static int cmd_print(int ac, char *av[])
602 {
603  int r = rpmaugPrint(NULL, stdout, cleanpath(av[0]));
604  err_check();
605  return r;
606 }
607 
608 static int cmd_save(int ac, /*@unused@*/ char *av[])
609 {
610  int r = rpmaugSave(NULL);
611 
612  if (r == -1) {
613  rpmaugFprintf(NULL, "Saving failed\n");
614  err_check();
615  } else {
616  r = rpmaugMatch(NULL, "/augeas/events/saved", NULL);
617  if (r > 0)
618  rpmaugFprintf(NULL, "Saved %d file(s)\n", r);
619  else if (r < 0)
620  rpmaugFprintf(NULL, "Error during match: %d\n", r);
621  }
622  return r;
623 }
624 
625 static int cmd_load(int ac, /*@unused@*/ char *av[])
626 {
627  int r = rpmaugLoad(NULL);
628  if (r == -1) {
629  rpmaugFprintf(NULL, "Loading failed\n");
630  err_check();
631  } else {
632  r = rpmaugMatch(NULL, "/augeas/events/saved", NULL);
633  if (r > 0)
634  rpmaugFprintf(NULL, "Saved %d file(s)\n", r);
635  else if (r < 0)
636  rpmaugFprintf(NULL, "Error during match: %d\n", r);
637  }
638  return r;
639 }
640 
641 static int cmd_ins(int ac, char *av[])
642 {
643  const char *label = av[0];
644  const char *where = av[1];
645  const char *path = cleanpath(av[2]);
646  int before;
647  int r = -1; /* assume failure */
648 
649  if (!strcmp(where, "after"))
650  before = 0;
651  else if (!strcmp(where, "before"))
652  before = 1;
653  else {
654  rpmaugFprintf(NULL, "The <WHERE> argument must be either 'before' or 'after'.");
655  goto exit;
656  }
657 
658  r = rpmaugInsert(NULL, path, label, before);
659  err_check();
660 
661 exit:
662  return r;
663 }
664 
665 static int cmd_help(int ac, /*@unused@*/ char *av[])
666 {
667  const struct poptOption * c;
668 
669  rpmaugFprintf(NULL, "Commands:\n\n");
670  for (c = _rpmaugCommandTable; c->longName != NULL; c++) {
671  rpmaugFprintf(NULL, " %s %s\n %s\n\n",
672  c->longName, (c->argDescrip ? c->argDescrip : ""), c->descrip);
673  }
674  rpmaugFprintf(NULL, "\nEnvironment:\n\n");
675  rpmaugFprintf(NULL, " AUGEAS_ROOT\n the file system root, defaults to '/'\n\n");
676  rpmaugFprintf(NULL, " AUGEAS_LENS_LIB\n colon separated list of directories with lenses,\n\
677  defaults to " AUGEAS_LENS_DIR "\n\n");
678  return 0;
679 }
680 
681 #define ARGMINMAX(_min, _max) (int)(((_min) << 8) | ((_max) & 0xff))
682 
683 const struct poptOption _rpmaugCommandTable[] = {
684  { "ls", '\0', POPT_ARG_MAINCALL, (void *)cmd_ls, ARGMINMAX(1, 1),
685  N_("List the direct children of PATH"), N_("<PATH>")
686  },
687  { "match", '\0', POPT_ARG_MAINCALL, (void *)cmd_match, ARGMINMAX(1, 2),
688  N_("Find all paths that match the path expression PATH. If VALUE is given,\n"
689  " only the matching paths whose value equals VALUE are printed"),
690  N_("<PATH> [<VALUE>]")
691  },
692  { "rm", '\0', POPT_ARG_MAINCALL, (void *)cmd_rm, ARGMINMAX(1, 1),
693  N_("Delete PATH and all its children from the tree"), N_("<PATH>")
694  },
695  { "mv", '\0', POPT_ARG_MAINCALL, (void *)cmd_mv, ARGMINMAX(2, 2),
696  N_("Move node SRC to DST. SRC must match exactly one node in the tree.\n"
697  " DST must either match exactly one node in the tree, or may not\n"
698  " exist yet. If DST exists already, it and all its descendants are\n"
699  " deleted. If DST does not exist yet, it and all its missing \n"
700  " ancestors are created."),
701  N_("<SRC> <DST>")
702  },
703  { "set", '\0', POPT_ARG_MAINCALL, (void *)cmd_set, ARGMINMAX(1, 2),
704  N_("Associate VALUE with PATH. If PATH is not in the tree yet,\n"
705  " it and all its ancestors will be created. These new tree entries\n"
706  " will appear last amongst their siblings"),
707  N_("<PATH> <VALUE>")
708  },
709  { "clear", '\0', POPT_ARG_MAINCALL, (void *)cmd_clear, ARGMINMAX(1, 1),
710  N_("Set the value for PATH to NULL. If PATH is not in the tree yet,\n"
711  " it and all its ancestors will be created. These new tree entries\n"
712  " will appear last amongst their siblings"),
713  N_("<PATH>")
714  },
715  { "get", '\0', POPT_ARG_MAINCALL, (void *)cmd_get, ARGMINMAX(1, 1),
716  N_("Print the value associated with PATH"), N_("<PATH>")
717  },
718  { "print", '\0', POPT_ARG_MAINCALL, (void *)cmd_print, ARGMINMAX(0, 1),
719  N_("Print entries in the tree. If PATH is given, printing starts there,\n"
720  " otherwise the whole tree is printed"),
721  N_("[<PATH>]")
722  },
723  { "ins", '\0', POPT_ARG_MAINCALL, (void *)cmd_ins, ARGMINMAX(3, 3),
724  N_("Insert a new node with label LABEL right before or after PATH into\n"
725  " the tree. WHERE must be either 'before' or 'after'."),
726  N_("<LABEL> <WHERE> <PATH>")
727  },
728  { "save", '\0', POPT_ARG_MAINCALL, (void *)cmd_save, ARGMINMAX(0, 0),
729  N_("Save all pending changes to disk. For now, files are not overwritten.\n"
730  " Instead, new files with extension .augnew are created"),
731  NULL
732  },
733  { "load", '\0', POPT_ARG_MAINCALL, (void *)cmd_load, ARGMINMAX(0, 0),
734  N_("Load files accordig to the transforms in /augeas/load."), NULL
735  },
736  { "defvar", '\0', POPT_ARG_MAINCALL, (void *)cmd_defvar, ARGMINMAX(1, 2),
737  N_("Define the variable NAME to the result of evalutating EXPR. The\n"
738  " variable can be used in path expressions as $NAME. Note that EXPR\n"
739  " is evaluated when the variable is defined, not when it is used."),
740  N_("<NAME> <EXPR>")
741  },
742  { "defnode", '\0', POPT_ARG_MAINCALL, (void *)cmd_defnode, ARGMINMAX(2, 3),
743  N_("Define the variable NAME to the result of evalutating EXPR, which\n"
744  " must be a nodeset. If no node matching EXPR exists yet, one\n"
745  " is created and NAME will refer to it. If VALUE is given, this\n"
746  " is the same as 'set EXPR VALUE'; if VALUE is not given, the\n"
747  " node is created as if with 'clear EXPR' would and NAME refers\n"
748  " to that node."),
749  N_("<NAME> <EXPR> [<VALUE>]")
750  },
751  { "exit", '\0', POPT_ARG_MAINCALL, (void *)cmd_quit, ARGMINMAX(0, 0),
752  N_("Exit the program"), NULL
753  },
754  { "quit", '\0', POPT_ARG_MAINCALL, (void *)cmd_quit, ARGMINMAX(0, 0),
755  N_("Exit the program"), NULL
756  },
757  { "help", '\0', POPT_ARG_MAINCALL, (void *)cmd_help, ARGMINMAX(0, 0),
758  N_("Print this help text"), NULL
759  },
760  { NULL, '\0', 0, NULL, ARGMINMAX(0, 0), NULL, NULL }
761 };
762 
763 rpmRC rpmaugRun(rpmaug aug, const char * str, const char ** resultp)
764 {
765  rpmioP P = NULL;
766  rpmRC rc = RPMRC_OK; /* assume success */
767  int xx;
768 
769 #ifdef WITH_AUGEAS
770  if (aug == NULL) aug = rpmaugI();
771 #else
772  if (aug == NULL) return rc; /* XXX FIXME */
773 #endif
774 
775  if (resultp)
776  *resultp = NULL;
777 
778  while (rpmioParse(&P, str) != RPMRC_NOTFOUND) { /* XXX exit on EOS */
779  const struct poptOption * c;
780  int (*handler) (int ac, char * av[]);
781  int minargs;
782  int maxargs;
783 
784  str = NULL;
785 
786  if (!(P->av && P->ac > 0 && P->av[0] != NULL && strlen(P->av[0]) > 0))
787  continue;
788 
789  for (c = _rpmaugCommandTable; c->longName; c++) {
790  if (strcmp(P->av[0], c->longName))
791  continue;
792  handler = (int (*)(int, char**)) c->arg;
793  minargs = (c->val >> 8) & 0xff;
794  maxargs = (c->val ) & 0xff;
795  break;
796  }
797  if (c->longName == NULL) {
798  rpmaugFprintf(NULL, "Unknown command '%s'\n", P->av[0]);
799  rc = RPMRC_FAIL;
800  } else
801  if ((P->ac - 1) < minargs) {
802  rpmaugFprintf(NULL, "Not enough arguments for %s\n", c->longName);
803  rc = RPMRC_FAIL;
804  } else
805  if ((P->ac - 1) > maxargs) {
806  rpmaugFprintf(NULL, "Too many arguments for %s\n", c->longName);
807  rc = RPMRC_FAIL;
808  } else
809  if ((xx = (*handler)(P->ac-1, (char **)P->av+1)) < 0) {
810  /* XXX return immediately on quit and exit commands */
811  if (!strcmp(c->longName, "quit") || !strcmp(c->longName, "exit"))
812  rc = RPMRC_NOTFOUND;
813  else {
814  rpmaugFprintf(NULL, "Failed(%d): %s\n", xx, P->av[0]);
815  rc = RPMRC_FAIL;
816  }
817  }
818 
819  if (rc != RPMRC_OK)
820  break;
821  }
822  if (aug != NULL) {
823  rpmiob iob = aug->iob;
824  if (resultp && iob->blen > 0) /* XXX return result iff bytes appended */
825  *resultp = rpmiobStr(iob);
826  iob->blen = 0; /* XXX reset the print buffer */
827  }
828  if (P != NULL) {
829  P->str = _free(P->str);
830  P->av = argvFree(P->av);
831  P = _free(P);
832  }
833  return rc;
834 }
const bson * b
Definition: bson.h:280
const char ** av
Definition: rpmiotypes.h:72
static int cmd_help(int ac, char *av[])
Definition: rpmaug.c:665
int rpmaugRm(rpmaug aug, const char *path)
Remove node and associated sub-tree.
Definition: rpmaug.c:236
const char * _rpmaugLoadpath
Definition: rpmaug.c:79
static int cmd_ls(int ac, char *av[])
Definition: rpmaug.c:436
const char * _rpmaugRoot
Definition: rpmaug.c:76
static int cmd_quit(int ac, char *av[])
Definition: rpmaug.c:431
#define EXIT_FAILURE
static char * ls_pattern(const char *path)
Definition: rpmaug.c:404
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
static int cmd_load(int ac, char *av[])
Definition: rpmaug.c:625
static int cmd_set(int ac, char *av[])
Definition: rpmaug.c:531
rpmioPool _rpmaugPool
Definition: rpmaug.c:58
int rpmaugLoad(rpmaug aug)
Load files/lenses from disk.
Definition: rpmaug.c:292
static int child_count(const char *path)
Definition: rpmaug.c:418
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
static int cmd_mv(int ac, char *av[])
Definition: rpmaug.c:519
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:77
#define SEP
Definition: rpmaug.c:351
rpmaug rpmaugLink(rpmaug aug)
Reference a augeas wrapper instance.
rpmRC rpmaugRun(rpmaug aug, const char *str, const char **resultp)
Run augeas commands from a buffer.
Definition: rpmaug.c:763
static int cmd_clear(int ac, char *av[])
Definition: rpmaug.c:574
struct poptOption rpmaugPoptTable[]
Popt option table for options to configure Augeas augtool.
Definition: rpmaug.c:109
unsigned int _rpmaugFlags
Definition: rpmaug.c:80
const char ** _rpmaugLoadargv
Definition: rpmaug.c:107
static int cmd_defnode(int ac, char *av[])
Definition: rpmaug.c:555
static int cmd_print(int ac, char *av[])
Definition: rpmaug.c:601
const char * str
Definition: bson.h:593
Yet Another syslog(3) API clone.
static const char _root[]
Definition: rpmaug.c:75
static int cmd_defvar(int ac, char *av[])
Definition: rpmaug.c:543
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
#define N_(Text)
Definition: system.h:531
static char * cleanstr(char *path, const char sep)
Definition: rpmaug.c:370
int rpmaugDefvar(rpmaug aug, const char *name, const char *expr)
Define an augeas variable.
Definition: rpmaug.c:165
struct rpmaug_s * rpmaug
Definition: rpmaug.h:14
static int xisspace(int c)
Definition: rpmiotypes.h:555
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
int rpmaugMv(rpmaug aug, const char *src, const char *dst)
Move src node to dst node.
Definition: rpmaug.c:250
char * progname
Definition: rpmdeps.c:20
char * str
Definition: rpmiotypes.h:70
int rpmaugSet(rpmaug aug, const char *path, const char *value)
Set the value associated with a path.
Definition: rpmaug.c:208
static char * cleanpath(char *path)
Definition: rpmaug.c:380
const struct poptOption _rpmaugCommandTable[]
Definition: rpmaug.c:683
int rpmaugDefnode(rpmaug aug, const char *name, const char *expr, const char *value, int *created)
Define an augeas node.
Definition: rpmaug.c:179
static int cmd_get(int ac, char *av[])
Definition: rpmaug.c:585
static void err_check(void)
Definition: rpmaug.c:385
rpmaug _rpmaugI
Definition: rpmaug.c:36
int rpmaugPrint(rpmaug aug, FILE *out, const char *path)
Print node paths that match an expression.
Definition: rpmaug.c:306
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
int rpmaugMatch(rpmaug aug, const char *path, char ***matches)
Return path(s) in tree that match an expression.
Definition: rpmaug.c:264
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
static rpmaug rpmaugGetPool(rpmioPool pool)
Definition: rpmaug.c:60
static int cmd_match(int ac, char *av[])
Definition: rpmaug.c:466
enum rpmRC_e rpmRC
RPM return codes.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:112
#define ARGMINMAX(_min, _max)
Definition: rpmaug.c:681
const char const int i
Definition: bson.h:778
const char const bson const bson bson * out
Definition: mongo.h:678
static int vsnprintf(char *buf, int nb, const char *fmt, va_list ap)
Definition: rpmps.c:212
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
int rpmaugGet(rpmaug aug, const char *path, const char **value)
Get the value associated with a path.
Definition: rpmaug.c:194
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
int rpmaugSave(rpmaug aug)
Save changed files to disk, appending .augnew or .augsave as requested.
Definition: rpmaug.c:278
static const char _loadpath[]
Definition: rpmaug.c:78
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:60
static int cmd_rm(int ac, char *av[])
Definition: rpmaug.c:507
static int cmd_save(int ac, char *av[])
Definition: rpmaug.c:608
#define minor(dev)
Definition: system.h:141
static const char * name
rpmaug rpmaugNew(const char *root, const char *loadpath, unsigned int flags)
Create and load a augeas wrapper.
Definition: rpmaug.c:132
const char const char * pattern
Definition: bson.h:971
#define xmalloc
Definition: system.h:32
int rpmaugInsert(rpmaug aug, const char *path, const char *label, int before)
Insert new sibling node before/after a given node.
Definition: rpmaug.c:222
static int cmd_ins(int ac, char *av[])
Definition: rpmaug.c:641
static void rpmaugFini(void *_aug)
Definition: rpmaug.c:39
#define AUGEAS_LENS_DIR
Definition: rpmaug.c:358
#define xrealloc
Definition: system.h:35
int _rpmaug_debug
Definition: rpmaug.c:33
int ac
Definition: rpmiotypes.h:73
rpmRC rpmioParse(rpmioP *Pptr, const char *str)
Parse next command out of a string incrementally.
Definition: poptIO.c:966
__attribute__((visibility("hidden"))) int mayAddToFilesAwaitingFiletriggers(const char *rootDir
void rpmaugFprintf(rpmaug aug, const char *fmt,...)
Append augeas output to an iob.
Definition: rpmaug.c:322