/* Kernel info for virtual domains. * (C) Copyright 2008-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Generic output routines which can write either plain * text tables or CSV files. */ #include #include #include #include #include #include "internal.h" static char *convert_fs_to_strings (const char *fs); static void output_to_csv (int to_strings, const char *fs, va_list args); void output_heading (const char *fs, ...) { va_list args; va_start (args, fs); if (!csv) { /* Convert each %..x in the format string into %..s */ char *fs2 = convert_fs_to_strings (fs); vprintf (fs2, args); free (fs2); printf ("\n"); } else output_to_csv (1, fs, args); va_end (args); } void output_row (const char *fs, ...) { va_list args; va_start (args, fs); if (!csv) { vprintf (fs, args); printf ("\n"); } else output_to_csv (0, fs, args); va_end (args); } /* Return a newly allocated format string with each '%..x' sequence * converted to '%..s'. We only attempt to parse simple format * strings, and we assume the length of the format string won't * change. */ static const char *end_of_specifier = "diouxXeEfFgGaAcsp%"; static char * convert_fs_to_strings (const char *fs) { char *fs2; int i, len; len = strlen (fs); fs2 = strdup (fs); for (i = 0; i < len; ++i) { if (fs2[i] == '%') { /* Search for the end of the %-sequence. */ do { i++; } while (i < len && strchr (end_of_specifier, fs2[i]) == NULL); if (i == len) internal_error (_("unrecognized format string in output_heading function")); fs2[i] = 's'; } } return fs2; /* caller frees */ } /* Output a row to a CSV file. The format string is just used to * get the correct types for each parameter - any non-%-specifiers * in the format string are ignored. If to_strings is true, then * each parameter is assumed to be a string. * * The CSV output is very conservative, designed to be correct * rather than concise. */ static void output_to_csv (int to_strings, const char *fs, va_list args) { int i, j, len, comma = 0; char fs2[16]; len = strlen (fs); for (i = 0; i < len; ++i) { /* Look for the next %-specifier. */ if (fs[i] == '%') { j = 0; do { fs2[j++] = fs[i++]; } while (j < sizeof (fs2) - 1 && i < len && strchr (end_of_specifier, fs[i]) == NULL); if (j == sizeof (fs2) - 1 || i == len) internal_error (_("unrecognized format string in output_* function")); fs2[j] = fs[i++]; fs2[j+1] = '\0'; } if (fs2[j] != '%') { char *str; int len2; if (to_strings) fs2[j] = 's'; /* Convert the next parameter into a string. */ if (vasprintf (&str, fs2, args) == -1) internal_error (_("unable to convert next argument to string using '%s'"), fs2); len2 = strlen (str); /* Output the next parameter as a CSV field. */ if (comma) putchar (','); comma = 1; putchar ('"'); for (j = 0; j < len2; ++j) { switch (str[j]) { case '"': putchar ('"'); putchar ('"'); break; case '\0': putchar ('"'); putchar ('0'); break; default: putchar (str[j]); } } putchar ('"'); free (str); } } putchar ('\n'); }