LCOV - code coverage report
Current view: top level - config - dump.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 116 116 100.0 %
Date: 2020-09-01 11:23:34 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  * Dump all the config
       4             :  *
       5             :  * @authors
       6             :  * Copyright (C) 2017-2018 Richard Russon <rich@flatcap.org>
       7             :  *
       8             :  * @copyright
       9             :  * This program is free software: you can redistribute it and/or modify it under
      10             :  * the terms of the GNU General Public License as published by the Free Software
      11             :  * Foundation, either version 2 of the License, or (at your option) any later
      12             :  * version.
      13             :  *
      14             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      15             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      16             :  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
      17             :  * details.
      18             :  *
      19             :  * You should have received a copy of the GNU General Public License along with
      20             :  * this program.  If not, see <http://www.gnu.org/licenses/>.
      21             :  */
      22             : 
      23             : /**
      24             :  * @page config_dump Dump all the config
      25             :  *
      26             :  * Dump all the config items in various formats.
      27             :  */
      28             : 
      29             : #include "config.h"
      30             : #include <stdbool.h>
      31             : #include <stdio.h>
      32             : #include "mutt/lib.h"
      33             : #include "dump.h"
      34             : #include "set.h"
      35             : #include "subset.h"
      36             : #include "types.h"
      37             : 
      38             : void mutt_pretty_mailbox(char *buf, size_t buflen);
      39             : 
      40             : /**
      41             :  * escape_string - Write a string to a buffer, escaping special characters
      42             :  * @param buf Buffer to write to
      43             :  * @param src String to write
      44             :  * @retval num Bytes written to buffer
      45             :  */
      46         120 : size_t escape_string(struct Buffer *buf, const char *src)
      47             : {
      48         120 :   if (!buf || !src)
      49           4 :     return 0;
      50             : 
      51         116 :   size_t len = 0;
      52         944 :   for (; *src; src++)
      53             :   {
      54         828 :     switch (*src)
      55             :     {
      56           2 :       case '\007':
      57           2 :         len += mutt_buffer_addstr(buf, "\\g");
      58           2 :         break;
      59           2 :       case '\n':
      60           2 :         len += mutt_buffer_addstr(buf, "\\n");
      61           2 :         break;
      62           2 :       case '\r':
      63           2 :         len += mutt_buffer_addstr(buf, "\\r");
      64           2 :         break;
      65           2 :       case '\t':
      66           2 :         len += mutt_buffer_addstr(buf, "\\t");
      67           2 :         break;
      68         820 :       default:
      69         820 :         if ((*src == '\\') || (*src == '"'))
      70           4 :           len += mutt_buffer_addch(buf, '\\');
      71         820 :         len += mutt_buffer_addch(buf, src[0]);
      72             :     }
      73             :   }
      74         116 :   return len;
      75             : }
      76             : 
      77             : /**
      78             :  * pretty_var - Escape and stringify a config item value
      79             :  * @param str    String to escape
      80             :  * @param buf    Buffer to write to
      81             :  * @retval num Number of bytes written to buffer
      82             :  */
      83         118 : size_t pretty_var(const char *str, struct Buffer *buf)
      84             : {
      85         118 :   if (!buf || !str)
      86           4 :     return 0;
      87             : 
      88         114 :   int len = 0;
      89             : 
      90         114 :   len += mutt_buffer_addch(buf, '"');
      91         114 :   len += escape_string(buf, str);
      92         114 :   len += mutt_buffer_addch(buf, '"');
      93             : 
      94         114 :   return len;
      95             : }
      96             : 
      97             : /**
      98             :  * dump_config_neo - Dump the config in the style of NeoMutt
      99             :  * @param cs      Config items
     100             :  * @param he      HashElem representing config item
     101             :  * @param value   Current value of the config item
     102             :  * @param initial Initial value of the config item
     103             :  * @param flags   Flags, see #ConfigDumpFlags
     104             :  * @param fp      File pointer to write to
     105             :  */
     106         148 : void dump_config_neo(struct ConfigSet *cs, struct HashElem *he, struct Buffer *value,
     107             :                      struct Buffer *initial, ConfigDumpFlags flags, FILE *fp)
     108             : {
     109         148 :   if (!he || !value || !fp)
     110          32 :     return;
     111             : 
     112         116 :   const char *name = he->key.strkey;
     113             : 
     114         116 :   if ((flags & CS_DUMP_ONLY_CHANGED) &&
     115          28 :       (!initial || mutt_str_equal(value->data, initial->data)))
     116             :   {
     117          26 :     return;
     118             :   }
     119             : 
     120          90 :   if (he->type == DT_SYNONYM)
     121             :   {
     122           2 :     const struct ConfigDef *cdef = he->data;
     123           2 :     const char *syn = (const char *) cdef->initial;
     124           2 :     fprintf(fp, "# synonym: %s -> %s\n", name, syn);
     125           2 :     return;
     126             :   }
     127             : 
     128          88 :   if (flags & CS_DUMP_SHOW_DOCS)
     129             :   {
     130          26 :     const struct ConfigDef *cdef = he->data;
     131          26 :     fprintf(fp, "# %s\n", cdef->docs);
     132             :   }
     133             : 
     134          88 :   bool show_name = !(flags & CS_DUMP_HIDE_NAME);
     135          88 :   bool show_value = !(flags & CS_DUMP_HIDE_VALUE);
     136             : 
     137          88 :   if (show_name && show_value)
     138          62 :     fprintf(fp, "set ");
     139          88 :   if (show_name)
     140          88 :     fprintf(fp, "%s", name);
     141          88 :   if (show_name && show_value)
     142          62 :     fprintf(fp, " = ");
     143          88 :   if (show_value)
     144          62 :     fprintf(fp, "%s", value->data);
     145          88 :   if (show_name || show_value)
     146          88 :     fprintf(fp, "\n");
     147             : 
     148          88 :   if (flags & CS_DUMP_SHOW_DEFAULTS)
     149             :   {
     150          28 :     const struct ConfigSetType *cst = cs_get_type_def(cs, he->type);
     151          28 :     if (cst)
     152          28 :       fprintf(fp, "# %s %s %s\n", cst->name, name, value->data);
     153             :   }
     154             : 
     155          88 :   if (flags & CS_DUMP_SHOW_DOCS)
     156          26 :     fprintf(fp, "\n");
     157             : }
     158             : 
     159             : /**
     160             :  * dump_config - Write all the config to a file
     161             :  * @param cs    ConfigSet to dump
     162             :  * @param flags Flags, see #ConfigDumpFlags
     163             :  * @param fp    File to write config to
     164             :  */
     165          14 : bool dump_config(struct ConfigSet *cs, ConfigDumpFlags flags, FILE *fp)
     166             : {
     167          14 :   if (!cs)
     168           2 :     return false;
     169             : 
     170          12 :   struct HashElem *he = NULL;
     171             : 
     172          12 :   struct HashElem **list = get_elem_list(cs);
     173          12 :   if (!list)
     174             :     return false; /* LCOV_EXCL_LINE */
     175             : 
     176          12 :   bool result = true;
     177             : 
     178          12 :   struct Buffer value = mutt_buffer_make(256);
     179          12 :   struct Buffer initial = mutt_buffer_make(256);
     180          12 :   struct Buffer tmp = mutt_buffer_make(256);
     181             : 
     182         162 :   for (size_t i = 0; list[i]; i++)
     183             :   {
     184         150 :     mutt_buffer_reset(&value);
     185         150 :     mutt_buffer_reset(&initial);
     186         150 :     he = list[i];
     187         150 :     const int type = DTYPE(he->type);
     188             : 
     189         150 :     if ((type == DT_SYNONYM) && !(flags & CS_DUMP_SHOW_SYNONYMS))
     190          10 :       continue;
     191             : 
     192         140 :     if ((he->type & DT_DEPRECATED) && !(flags & CS_DUMP_SHOW_DEPRECATED))
     193          10 :       continue;
     194             : 
     195             :     // if ((type == DT_DISABLED) && !(flags & CS_DUMP_SHOW_DISABLED))
     196             :     //   continue;
     197             : 
     198         130 :     if (type != DT_SYNONYM)
     199             :     {
     200             :       /* If necessary, get the current value */
     201         130 :       if ((flags & CS_DUMP_ONLY_CHANGED) || !(flags & CS_DUMP_HIDE_VALUE) ||
     202          26 :           (flags & CS_DUMP_SHOW_DEFAULTS))
     203             :       {
     204         130 :         int rc = cs_he_string_get(cs, he, &value);
     205         130 :         if (CSR_RESULT(rc) != CSR_SUCCESS)
     206             :         {
     207             :           result = false; /* LCOV_EXCL_LINE */
     208             :           break;          /* LCOV_EXCL_LINE */
     209             :         }
     210             : 
     211         130 :         const struct ConfigDef *cdef = he->data;
     212         130 :         if ((type == DT_STRING) && IS_SENSITIVE(*cdef) &&
     213          10 :             (flags & CS_DUMP_HIDE_SENSITIVE) && !mutt_buffer_is_empty(&value))
     214             :         {
     215           2 :           mutt_buffer_reset(&value);
     216           2 :           mutt_buffer_addstr(&value, "***");
     217             :         }
     218             : 
     219         130 :         if (((type == DT_PATH) || IS_MAILBOX(he)) && (value.data[0] == '/'))
     220          10 :           mutt_pretty_mailbox(value.data, value.dsize);
     221             : 
     222         130 :         if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
     223          80 :             (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
     224             :         {
     225          80 :           mutt_buffer_reset(&tmp);
     226          80 :           pretty_var(value.data, &tmp);
     227          80 :           mutt_buffer_strcpy(&value, tmp.data);
     228             :         }
     229             :       }
     230             : 
     231             :       /* If necessary, get the default value */
     232         130 :       if (flags & (CS_DUMP_ONLY_CHANGED | CS_DUMP_SHOW_DEFAULTS))
     233             :       {
     234          52 :         int rc = cs_he_initial_get(cs, he, &initial);
     235          52 :         if (CSR_RESULT(rc) != CSR_SUCCESS)
     236             :         {
     237             :           result = false; /* LCOV_EXCL_LINE */
     238             :           break;          /* LCOV_EXCL_LINE */
     239             :         }
     240             : 
     241          52 :         if (((type == DT_PATH) || IS_MAILBOX(he)) && !(he->type & DT_MAILBOX))
     242           4 :           mutt_pretty_mailbox(initial.data, initial.dsize);
     243             : 
     244          52 :         if ((type != DT_BOOL) && (type != DT_NUMBER) && (type != DT_LONG) &&
     245          32 :             (type != DT_QUAD) && !(flags & CS_DUMP_NO_ESCAPING))
     246             :         {
     247          32 :           mutt_buffer_reset(&tmp);
     248          32 :           pretty_var(initial.data, &tmp);
     249          32 :           mutt_buffer_strcpy(&initial, tmp.data);
     250             :         }
     251             :       }
     252             :     }
     253             : 
     254         130 :     dump_config_neo(cs, he, &value, &initial, flags, fp);
     255             :   }
     256             : 
     257          12 :   FREE(&list);
     258          12 :   mutt_buffer_dealloc(&value);
     259          12 :   mutt_buffer_dealloc(&initial);
     260          12 :   mutt_buffer_dealloc(&tmp);
     261             : 
     262          12 :   return result;
     263             : }

Generated by: LCOV version 1.15