[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Machine readable ausearch output



Steve Grubb <sgrubb redhat com> writes:

> I am also planning to pull the ausearch program apart and make a
> library that people could use to access records programmatically. It
> might be better to use this to create a translator program.
...
> Do any of these sound like they align with your needs?

A library that allows me to access the records programmatically is the
most desirable solution from my perspective.  You see, what I'd like
to do is to translate each record into nested Python dictionaries, in
which every key in a dictionary is a string.  I have enclosed the code
with which I would like to do the translation so as to give you a
concrete instance of this approach.

John

/*
  Python dictionary pretty printing.
  Copyright (C) 2005 The MITRE Corporation

  Author: John D. Ramsdell

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  After initializing the pretty printer, Python values are constructed
  and then printed.  A Python value is either a string or a dictionary
  containing an unordered sequence of key-value entries.  The key is a
  string.  If initialized with the string "pyval", the print function
  generates a textual representation of the Python value prefixed by
  the string "pyval(", and followed by the string ")".  A Python
  script can use execfile to read the generated data after providing a
  definition for the function pyval.
*/

#if !defined PYVAL_H
#define PYVAL_H

typedef struct pyval *pyval_t;

/* Set the Python function to be called with the printed dictionary.
   Call this before building any Python dictioraries. */
void pyval_init(const char *function);

/* Construct a string value.  Returns null if given it. */
pyval_t pyval_string(const char *value);

/* Construct an empty dictionary. */
pyval_t pyval_dictionary(void);

/* Add a key value entry to a dictionary.  Returns null if given a bad
   argument. */
pyval_t pyval_entry(const char *key, pyval_t value, pyval_t dictionary);

/* Print Python value.  Return zero on success.  In all cases, the
   memory allocated for the Python value is freed. */
int pyval_print(FILE *out, pyval_t value, int margin);

#endif
/*
  A generic pretty printer.
  Copyright (C) 2005 The MITRE Corporation

  Author: John D. Ramsdell -- December 2002

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  See pprint.h for a description of the interface.

  The alogithm is by Lawrence C. Paulson, who simplified an algorithm
  by Derek C. Oppen.

  Derek C. Oppen, Prettyprinting, ACM Transactions on Programming
  Languages and Systems, Vol 2, No. 4, October 1980, Pages 465-483.

  The pretty printer is based on ML programs with the following
  copyright:

(**** ML Programs from Chapter 8 of

  ML for the Working Programmer, 2nd edition
  by Lawrence C. Paulson, Computer Laboratory, University of Cambridge.
  (Cambridge University Press, 1996)

Copyright (C) 1996 by Cambridge University Press.
Permission to copy without fee is granted provided that this copyright
notice and the DISCLAIMER OF WARRANTY are included in any copy.

DISCLAIMER OF WARRANTY.  These programs are provided `as is' without
warranty of any kind.  We make no warranties, express or implied, that the
programs are free of error, or are consistent with any particular standard
of merchantability, or that they will meet your requirements for any
particular application.  They should not be relied upon for solving a
problem whose incorrect solution could result in injury to a person or loss
of property.  If you do use the programs or functions in such a manner, it
is at your own risk.  The author and publisher disclaim all liability for
direct, incidental or consequential damages resulting from your use of
these programs or functions.
****)

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <obstack.h>
#include "pyval.h"

typedef struct pretty *pretty_t;

static void *
xmalloc(size_t size)
{
  void *value = malloc(size);
  if (!value) {
    fprintf(stderr, "Memory exhausted--malloc failed\n");
    exit(1);
  }
  return value;
}

typedef struct env {
  int space;
  int margin;
  FILE *out;
} *env_t;

struct pretty
{
  int length;
  int (*break_it)(env_t, pretty_t, int);
  void (*print_it)(env_t, pretty_t, int, int, int);
  union {
    const char *string;
    struct {
      int indent;
      pretty_t p;
    } blk;
  } u;
  pretty_t next;
};

static struct pretty error_marker[1];

/* Allocation using obstack */

#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free

static struct obstack stack[1];

static void
pprint_init(void)
{
  obstack_init(stack);
}

static pretty_t
alloc(void)
{
  return (pretty_t)obstack_alloc(stack, sizeof(struct pretty));
}

/* Helpers */

static void
blanks(env_t e, int n)
{
  for (; n > 0; n--) {
    fputc(' ', e->out);
    e->space--;
  }
}

static void
newline(env_t e)
{
  fputc('\n', e->out);
  e->space = e->margin;
}

static int
break_dist(env_t e, pretty_t p, int after)
{
  if (p)
    return p->break_it(e, p, after);
  else
    return after;
}

static void
printing(env_t e, pretty_t p, int block_space,
	 int after, int force_breaks)
{
  for (; p; p = p->next)
    p->print_it(e, p, block_space, after, force_breaks);
}

/* Strings */

static int
str_break_it(env_t e, pretty_t p, int after)
{
  return p->length + break_dist(e, p->next, after);
}

static void
str_print_it(env_t e, pretty_t p, int block_space,
	     int after, int force_breaks)
{
  fputs(p->u.string, e->out);
  e->space -= p->length;
}

static pretty_t
pstring(const char *string, pretty_t next)
{
  if (string && next != error_marker) {
    pretty_t p = alloc();
    if (!p)
      return error_marker;
    p->length = strlen(string);
    p->break_it = str_break_it;
    p->print_it = str_print_it;

    p->u.string = string;
    p->next = next;
    return p;
  }
  else
    return error_marker;
}

/* Unbreakable space */

static void
spc_print_it(env_t e, pretty_t p, int block_space,
	     int after, int force_breaks)
{
  int n = p->length;
  e->space -= n;
  while (n-- > 0)
    fputc(' ', e->out);
}

static pretty_t
pspace(int fill, pretty_t next)
{
  if (fill >= 0 && next != error_marker) {
    pretty_t p = alloc();
    if (!p)
      return error_marker;
    p->length = fill;
    p->break_it = str_break_it;
    p->print_it = spc_print_it;
    p->next = next;
    return p;
  }
  else
    return error_marker;
}

/* Breaks */

static int
brk_break_it(env_t e, pretty_t p, int after)
{
  return 0;
}

static void
brk_print_it(env_t e, pretty_t p, int block_space,
	     int after, int force_breaks)
{
  int len = p->length;
  if (!force_breaks && len + break_dist(e, p->next, after) <= e->space)
    blanks(e, len);
  else {
    newline(e);
    blanks(e, e->margin - block_space);
  }
}

static pretty_t
pbreak(int skip, pretty_t next)
{
  if (skip >= 0 && next != error_marker) {
    pretty_t p = alloc();
    if (!p)
      return error_marker;
    p->length = skip;
    p->break_it = brk_break_it;
    p->print_it = brk_print_it;
    p->next = next;
    return p;
  }
  else
    return error_marker;
}

/* Blocks */

static int
sum_length(pretty_t p)
{
  int sum = 0;
  for (; p; p = p->next)
    sum += p->length;
  return sum;
}

static void
blk_print_it(env_t e, pretty_t p, int block_space,
	     int after, int force_breaks)
{
  int dist = break_dist(e, p->next, after);
  printing(e, p->u.blk.p, e->space - p->u.blk.indent, dist, 0);
}

static pretty_t
pblock(int indent, pretty_t p, pretty_t next)
{
  if (p != error_marker && next != error_marker) {
    pretty_t r = alloc();
    if (!r)
      return error_marker;
    r->length = sum_length(p);
    r->break_it = str_break_it;
    r->print_it = blk_print_it;
    r->u.blk.indent = indent;
    r->u.blk.p = p;
    r->next = next;
    return r;
  }
  else
    return error_marker;
}

/* Groups */

static void
grp_print_it(env_t e, pretty_t p, int block_space,
	     int after, int force_breaks)
{
  int dist = break_dist(e, p->next, after);
  force_breaks = p->length + dist > e->space;
  printing(e, p->u.blk.p, e->space - p->u.blk.indent,
	   dist, force_breaks);
}

static pretty_t
pgroup(int indent, pretty_t p, pretty_t next)
{
  if (p != error_marker && next != error_marker) {
    pretty_t r = alloc();
    if (!r)
      return error_marker;
    r->length = sum_length(p);
    r->break_it = str_break_it;
    r->print_it = grp_print_it;
    r->u.blk.indent = indent;
    r->u.blk.p = p;
    r->next = next;
    return r;
  }
  else
    return error_marker;
}

/* the pretty printer */

static int
pprint(FILE *out, pretty_t pretty, int margin)
{
  if (pretty == error_marker) {
    obstack_free(stack, 0);
    pprint_init();
    return -1;
  }
  else {
    struct env e = { margin, margin, out };
    printing(&e, pretty, margin, 0, 0);
    obstack_free(stack, 0);
    pprint_init();
    return 0;
  }
}

/* The Python stuff */

static const char *pyfun = "pyval";

void
pyval_init(const char *string)
{
  pyfun = string;
  pprint_init();
}

typedef enum {
  PYVAL_STRING,
  PYVAL_ENTRY
} pyval_type_t;

struct pyval {
  pyval_type_t type;
  const char *string;
  pyval_t value;
  pyval_t next;
};

static pyval_t
pyalloc(void)
{
  return (pyval_t)obstack_alloc(stack, sizeof(struct pyval));
}

pyval_t
pyval_string(const char *string)
{
  if (!string)
    return 0;
  pyval_t pyval = pyalloc();
  pyval->type = PYVAL_STRING;
  pyval->string = string;
  pyval->value = 0;
  pyval->next = 0;
  return pyval;
}

static struct pyval empty_dictionary[1] = {
  {PYVAL_ENTRY, 0, 0, 0}
};

pyval_t pyval_dictionary(void)
{
  return empty_dictionary;
}

pyval_t
pyval_entry(const char *string, pyval_t value, pyval_t next)
{
  if (!string || !value || !next || next->type != PYVAL_ENTRY)
    return 0;
  pyval_t pyval = pyalloc();
  pyval->type = PYVAL_ENTRY;
  pyval->string = string;
  pyval->value = value;
  pyval->next = next;
  return pyval;
}

/* Python strings */

static size_t
pyval_strlen(const char *s)
{
  size_t n = 2;
  for (; *s; s++) {
    switch (*s) {
    case '\'':
    case '\\':
    case '\n':
      n += 2;
      break;
    default:
      n++;
    }
  }
  return n;
}

static void
pyval_str_print_it(env_t e, pretty_t p, int block_space,
		   int after, int force_breaks)
{
  const char *s = p->u.string;
  fputc('\'', e->out);
  for (; *s; s++) {
    switch (*s) {
    case '\'':
    case '\\':
    case '\n':
      fputc('\\', e->out);
    }
    fputc(*s, e->out);
  }
  fputc('\'', e->out);
  e->space -= p->length;
}

static pretty_t
pyval_pstring(const char *string, pretty_t next)
{
  if (string && next != error_marker) {
    pretty_t p = alloc();
    if (!p)
      return error_marker;
    p->length = pyval_strlen(string);
    p->break_it = str_break_it;
    p->print_it = pyval_str_print_it;

    p->u.string = string;
    p->next = next;
    return p;
  }
  else
    return error_marker;
}

static pretty_t pyval_pp(pyval_t, pretty_t);

static pretty_t
pyval_dict(pyval_t pyval, pretty_t next)
{
  pretty_t p;
  do {
    if (next == error_marker)
      return error_marker;
    switch (pyval->type) {
    case PYVAL_STRING:
      return error_marker;
    case PYVAL_ENTRY:
      if (next)
	next = pstring(",", pbreak(1, next));
      else
	next = pstring("}", next);
      p = pyval_pp(pyval->value, 0);
      p = pstring(":", pbreak(1, p));
      p = pyval_pstring(pyval->string, p);
      next = pblock(1, p, next);
      pyval = pyval->next;
      if (!pyval)
	return error_marker;
      break;
    default:
      return error_marker;
    }
  } while (pyval != empty_dictionary);
  return next;
}

static pretty_t
pyval_pp(pyval_t pyval, pretty_t next)
{
  if (next == error_marker || !pyval)
    return error_marker;
  switch (pyval->type) {
  case PYVAL_STRING:
    return pyval_pstring(pyval->string, next);
  case PYVAL_ENTRY:
    if (pyval == empty_dictionary)
      return pstring("{}", next);
    else
      return pblock(1, pstring("{", pyval_dict(pyval, 0)), next);
  default:
    return error_marker;
  }
}

int
pyval_print(FILE *out, pyval_t pyval, int margin)
{
  pretty_t p = pyval_pp(pyval, pstring(")", 0));
  p = pstring(pyfun, pstring("(", p));
  return pprint(out, p, margin);
}

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]