In data giovedì 27 agosto 2015 15:18:24, Maros Zatko ha scritto: > --- > cat/Makefile.am | 1 + > cat/log.c | 113 ++----------------------------------------- > fish/Makefile.am | 1 + > fish/journal.c | 142 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 147 insertions(+), 110 deletions(-) > create mode 100644 fish/journal.c > > diff --git a/cat/Makefile.am b/cat/Makefile.am > index d0db6fa..d472100 100644 > --- a/cat/Makefile.am > +++ b/cat/Makefile.am > @@ -38,6 +38,7 @@ bin_PROGRAMS = virt-cat virt-filesystems virt-log virt-ls > SHARED_SOURCE_FILES = \ > ../fish/domain.c \ > ../fish/inspect.c \ > + ../fish/journal.c \ > ../fish/keys.c \ > ../fish/options.h \ > ../fish/options.c \ > diff --git a/cat/log.c b/cat/log.c > index 616baed..c72946b 100644 > --- a/cat/log.c > +++ b/cat/log.c > @@ -36,6 +36,7 @@ > > #include "guestfs.h" > #include "options.h" > +#include "fish.h"
The change for this is in patch #2, while it needs to be part of this (otherwise it won't build alone). Also, I'd say to create a new own journal.h, so the global fish.h of guestfish is not pulled when using this shared code; see also fish/windows.{c,h}. > > /* Currently open libguestfs handle. */ > guestfs_h *g; > @@ -273,128 +274,20 @@ do_log (void) > return 0; > } > > -/* Find the value of the named field from the list of attributes. If > - * not found, returns NULL (not an error). If found, returns a > - * pointer to the field, and the length of the field. NOTE: The field > - * is NOT \0-terminated, so you have to print it using "%.*s". > - * > - * There may be multiple fields with the same name. In this case, the > - * function returns the first entry. > - */ > -static const char * > -get_journal_field (const struct guestfs_xattr_list *xattrs, const char *name, > - size_t *len_rtn) > -{ > - uint32_t i; > - > - for (i = 0; i < xattrs->len; ++i) { > - if (STREQ (name, xattrs->val[i].attrname)) { > - *len_rtn = xattrs->val[i].attrval_len; > - return xattrs->val[i].attrval; > - } > - } > - > - return NULL; /* not found */ > -} > - > -static const char *const log_level_table[] = { > - [LOG_EMERG] = "emerg", > - [LOG_ALERT] = "alert", > - [LOG_CRIT] = "crit", > - [LOG_ERR] = "err", > - [LOG_WARNING] = "warning", > - [LOG_NOTICE] = "notice", > - [LOG_INFO] = "info", > - [LOG_DEBUG] = "debug" > -}; > - > static int > do_log_journal (void) > { > int r; > - unsigned errors = 0; > - > if (guestfs_journal_open (g, JOURNAL_DIR) == -1) > return -1; > > - while ((r = guestfs_journal_next (g)) > 0) { > - CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL; > - const char *priority_str, *identifier, *comm, *pid, *message; > - size_t priority_len, identifier_len, comm_len, pid_len, message_len; > - int priority = LOG_INFO; > - int64_t ts; > - > - /* The question is what fields to display. We should probably > - * make this configurable, but for now use the "short" format from > - * journalctl. (XXX) > - */ > - > - xattrs = guestfs_journal_get (g); > - if (xattrs == NULL) > - return -1; > - > - ts = guestfs_journal_get_realtime_usec (g); /* error checked below */ > - > - priority_str = get_journal_field (xattrs, "PRIORITY", &priority_len); > - //hostname = get_journal_field (xattrs, "_HOSTNAME", &hostname_len); > - identifier = get_journal_field (xattrs, "SYSLOG_IDENTIFIER", > - &identifier_len); > - comm = get_journal_field (xattrs, "_COMM", &comm_len); > - pid = get_journal_field (xattrs, "_PID", &pid_len); > - message = get_journal_field (xattrs, "MESSAGE", &message_len); > - > - /* Timestamp. */ > - if (ts >= 0) { > - char buf[64]; > - time_t t = ts / 1000000; > - struct tm tm; > - > - if (strftime (buf, sizeof buf, "%b %d %H:%M:%S", > - localtime_r (&t, &tm)) <= 0) { > - fprintf (stderr, _("%s: could not format journal entry timestamp\n"), > - guestfs_int_program_name); > - errors++; > - continue; > - } > - fputs (buf, stdout); > - } > - > - /* Hostname. */ > - /* We don't print this because it is assumed each line from the > - * guest will have the same hostname. (XXX) > - */ > - //if (hostname) > - // printf (" %.*s", (int) hostname_len, hostname); > - > - /* Identifier. */ > - if (identifier) > - printf (" %.*s", (int) identifier_len, identifier); > - else if (comm) > - printf (" %.*s", (int) comm_len, comm); > - > - /* PID */ > - if (pid) > - printf ("[%.*s]", (int) pid_len, pid); > - > - /* Log level. */ > - if (priority_str && *priority_str >= '0' && *priority_str <= '7') > - priority = *priority_str - '0'; > - > - printf (" %s:", log_level_table[priority]); > - > - /* Message. */ > - if (message) > - printf (" %.*s", (int) message_len, message); > - > - printf ("\n"); > - } > - if (r == -1) /* error from guestfs_journal_next */ > + if ((r = journal_view ("~3axv")) == -1) Considering that journal_view just returns 0 for success and -1 for failure, there isn't even need to set its return value to r; just check for -1 as error condition. > return -1; > > if (guestfs_journal_close (g) == -1) > return -1; > > - return errors > 0 ? -1 : 0; > + return r; > } > > static int > diff --git a/fish/Makefile.am b/fish/Makefile.am > index c4b82ae..e4b4fcf 100644 > --- a/fish/Makefile.am > +++ b/fish/Makefile.am > @@ -94,6 +94,7 @@ guestfish_SOURCES = \ > glob.c \ > help.c \ > hexedit.c \ > + journal.c \ > lcd.c \ > man.c \ > more.c \ > diff --git a/fish/journal.c b/fish/journal.c > new file mode 100644 > index 0000000..9afdf60 > --- /dev/null > +++ b/fish/journal.c > @@ -0,0 +1,142 @@ > +/* guestfish - guest filesystem shell > + * Copyright (C) 2009-2015 Red Hat Inc. > + * > + * 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. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA. > + */ > + > +#include <config.h> > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <inttypes.h> > +#include <libintl.h> > +#include <time.h> > +#include <syslog.h> > + > +#include "fish.h" > +#include "journal.h" > + > +/* Find the value of the named field from the list of attributes. If > + * not found, returns NULL (not an error). If found, returns a > + * pointer to the field, and the length of the field. NOTE: The field > + * is NOT \0-terminated, so you have to print it using "%.*s". > + * > + * There may be multiple fields with the same name. In this case, the > + * function returns the first entry. > + */ > +static const char * > +get_journal_field (const struct guestfs_xattr_list *xattrs, const char *name, > + size_t *len_rtn) > +{ > + uint32_t i; > + > + for (i = 0; i < xattrs->len; ++i) { > + if (STREQ (name, xattrs->val[i].attrname)) { > + *len_rtn = xattrs->val[i].attrval_len; > + return xattrs->val[i].attrval; > + } > + } > + > + return NULL; /* not found */ > +} > + > +static const char *const log_level_table[] = { > + [LOG_EMERG] = "emerg", > + [LOG_ALERT] = "alert", > + [LOG_CRIT] = "crit", > + [LOG_ERR] = "err", > + [LOG_WARNING] = "warning", > + [LOG_NOTICE] = "notice", > + [LOG_INFO] = "info", > + [LOG_DEBUG] = "debug" > +}; > + > +static const char * > +lookup_field (char field) > +{ > + size_t i = 0; > + for (i = 0; i < sizeof journal_fields / sizeof *journal_fields; i += 2) { > + if (field == journal_fields[i][0]) > + return journal_fields[i+1]; > + } > + return NULL; > +} > + > +/* Fetch and print journal fields in specified order > + * default is '~3axv' > + */ > +int > +journal_view (const char *fields) > +{ > + int r; > + int errors = 0; > + while ((r = guestfs_journal_next(g)) > 0) { r seems unused here. > + CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL; > + int64_t ts; > + int priority = LOG_INFO; > + > + xattrs = guestfs_journal_get (g); > + if (xattrs == NULL) > + return -1; > + > + size_t f_id = 0; > + for (f_id = 0; f_id < strlen (fields); ++f_id) { > + if (fields[f_id] == '~') { > + ts = guestfs_journal_get_realtime_usec (g); > + /* Timestamp. */ > + if (ts >= 0) { > + char buf[64]; > + time_t t = ts / 1000000; > + struct tm tm; > + > + if (strftime (buf, sizeof buf, "%b %d %H:%M:%S", > + localtime_r (&t, &tm)) <= 0) { > + fprintf (stderr, _("could not format journal entry > timestamp\n")); > + errors++; > + continue; > + } > + fputs (buf, stdout); > + } > + } > + > + const char *field_name, *field_val; > + size_t field_len; > + if ((field_name = lookup_field (fields[f_id]))) { > + field_val = get_journal_field (xattrs, field_name, &field_len); > + if (STREQ (field_name, "PRIORITY")) { > + if (field_val && *field_val >= '0' && *field_val <= '7') > + priority = *field_val - '0'; > + printf (" %s:", log_level_table[priority]); > + } else if (field_val) { > + printf (" %.*s", (int)field_len, field_val); > + } > + } > + } > + printf ("\n"); > + } > + > + return errors > 0 ? -1 : 0; > +} > + > +int > +run_journal_view (const char *cmd, size_t argc, char *argv[]) > +{ > + if (argc > 0) > + return journal_view (argv[0]); > + return journal_view ("~3axv"); > +} > Thanks, -- Pino Toscano _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs