aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2019-11-24 13:26:47 +0100
committerFabian Groffen <grobian@gentoo.org>2019-11-24 13:26:47 +0100
commitabbfff8553d8e99d71d71054e81a7f21d6479221 (patch)
treee2ed6c47b9427b7ccdc27828d9a8252b9390f88f
parentlibq/xpak: fix out of bounds checking (diff)
downloadportage-utils-abbfff8553d8e99d71d71054e81a7f21d6479221.tar.gz
portage-utils-abbfff8553d8e99d71d71054e81a7f21d6479221.tar.bz2
portage-utils-abbfff8553d8e99d71d71054e81a7f21d6479221.zip
main: overhaul profile/config reading somewhat
- track where values come from, expose using -v (with q -[oe]) - follow repo-prefixed profiles in parent files (non-PMS feature?) - read usr/share/portage/config/repos.conf for repo defaults Signed-off-by: Fabian Groffen <grobian@gentoo.org>
-rw-r--r--applets.h1
-rw-r--r--main.c397
-rw-r--r--main.h1
-rw-r--r--man/q.16
-rw-r--r--q.c20
5 files changed, 254 insertions, 171 deletions
diff --git a/applets.h b/applets.h
index 364f457..e7b81f4 100644
--- a/applets.h
+++ b/applets.h
@@ -168,6 +168,7 @@ extern char *features;
extern char *install_mask;
extern DEFINE_ARRAY(overlays);
extern DEFINE_ARRAY(overlay_names);
+extern DEFINE_ARRAY(overlay_src);
extern char *main_overlay;
extern int twidth;
diff --git a/main.c b/main.c
index e236934..081d72a 100644
--- a/main.c
+++ b/main.c
@@ -44,6 +44,7 @@ char *features;
char *install_mask;
DECLARE_ARRAY(overlays);
DECLARE_ARRAY(overlay_names);
+DECLARE_ARRAY(overlay_src);
static char *portarch;
static char *portedb;
@@ -248,96 +249,6 @@ makeargv(const char *string, int *argc, char ***argv)
free(q);
}
-/* Handle a single file in the repos.conf format. */
-static void
-read_one_repos_conf(const char *repos_conf)
-{
- int nsec;
- char *conf;
- const char *main_repo, *repo, *path;
- dictionary *dict;
-
- if (getenv("DEBUG"))
- fprintf(stderr, " parse %s\n", repos_conf);
-
- dict = iniparser_load(repos_conf);
-
- main_repo = iniparser_getstring(dict, "DEFAULT:main-repo", NULL);
-
- nsec = iniparser_getnsec(dict);
- while (nsec-- > 0) {
- repo = iniparser_getsecname(dict, nsec);
- if (!strcmp(repo, "DEFAULT"))
- continue;
-
- xasprintf(&conf, "%s:location", repo);
- path = iniparser_getstring(dict, conf, NULL);
- if (path) {
- void *ele = xarraypush_str(overlays, path);
- xarraypush_str(overlay_names, repo);
- if (main_repo && !strcmp(repo, main_repo))
- main_overlay = ele;
- }
- free(conf);
- }
-
- iniparser_freedict(dict);
-}
-
-/* Handle a possible directory of files. */
-static void
-read_repos_conf(const char *configroot, const char *repos_conf)
-{
- char *top_conf, *sub_conf;
- int i, count;
- struct dirent **confs;
-
- xasprintf(&top_conf, "%s%s", configroot, repos_conf);
- if (getenv("DEBUG"))
- fprintf(stderr, "repos.conf.d scanner %s\n", top_conf);
- count = scandir(top_conf, &confs, NULL, alphasort);
- if (count == -1) {
- if (errno == ENOTDIR)
- read_one_repos_conf(top_conf);
- } else {
- for (i = 0; i < count; ++i) {
- const char *name = confs[i]->d_name;
-
- if (name[0] == '.' || name[0] == '\0')
- continue;
-
- /* Exclude backup files (aka files with ~ as postfix). */
- if (name[strlen(name) - 1] == '~')
- continue;
-
-#ifdef DT_UNKNOWN
- if (confs[i]->d_type != DT_UNKNOWN &&
- confs[i]->d_type != DT_REG &&
- confs[i]->d_type != DT_LNK)
- continue;
-#endif
-
- xasprintf(&sub_conf, "%s/%s", top_conf, name);
-
-#ifdef DT_UNKNOWN
- if (confs[i]->d_type != DT_REG)
-#endif
- {
- struct stat st;
- if (stat(sub_conf, &st) || !S_ISREG(st.st_mode)) {
- free(sub_conf);
- continue;
- }
- }
-
- read_one_repos_conf(sub_conf);
- free(sub_conf);
- }
- scandir_free(confs, count);
- }
- free(top_conf);
-}
-
static void
strincr_var(const char *name, const char *s, char **value, size_t *value_len)
{
@@ -406,19 +317,33 @@ get_portage_env_var(env_vars *vars, const char *name)
}
static void
-set_portage_env_var(env_vars *var, const char *value)
+set_portage_env_var(env_vars *var, const char *value, const char *src)
{
switch (var->type) {
case _Q_BOOL:
*var->value.b = 1;
+ free(var->src);
+ var->src = xstrdup(src);
break;
case _Q_STR:
free(*var->value.s);
*var->value.s = xstrdup(value);
var->value_len = strlen(value);
+ free(var->src);
+ var->src = xstrdup(src);
break;
case _Q_ISTR:
strincr_var(var->name, value, var->value.s, &var->value_len);
+ if (strcmp(var->src, "built-in default") == 0) {
+ free(var->src);
+ var->src = xstrdup(src);
+ } else {
+ size_t l = strlen(var->src) + 2 + strlen(src) + 1;
+ char *p = xmalloc(sizeof(char) * l);
+ snprintf(p, l, "%s, %s", var->src, src);
+ free(var->src);
+ var->src = p;
+ }
break;
}
}
@@ -426,27 +351,22 @@ set_portage_env_var(env_vars *var, const char *value)
/* Helper to read a portage env file (e.g. make.conf), or recursively if
* it points to a directory */
static void
-read_portage_env_file(const char *configroot, const char *file, env_vars vars[])
+read_portage_env_file(const char *file, env_vars vars[])
{
- size_t i, buflen, line, configroot_len, file_len;
FILE *fp;
struct dirent **dents;
int dentslen;
- char *buf, *s, *p;
+ char *s;
+ char *p;
+ char *buf = NULL;
+ size_t buflen = 0;
+ size_t line;
+ int i;
if (getenv("DEBUG"))
- fprintf(stderr, "profile %s/%s\n", configroot, file);
-
- configroot_len = strlen(configroot);
- file_len = strlen(file);
- buflen = configroot_len + file_len + 1;
- buf = xmalloc(buflen);
-
- memcpy(buf, configroot, configroot_len);
- memcpy(buf + configroot_len, file, file_len);
- buf[buflen - 1] = '\0';
+ fprintf(stderr, "profile %s\n", file);
- if ((dentslen = scandir(buf, &dents, NULL, alphasort)) > 0) {
+ if ((dentslen = scandir(file, &dents, NULL, alphasort)) > 0) {
int di;
struct dirent *d;
char npath[_Q_PATH_MAX * 2];
@@ -458,44 +378,41 @@ read_portage_env_file(const char *configroot, const char *file, env_vars vars[])
d->d_name[strlen(d->d_name) - 1] == '~')
continue;
snprintf(npath, sizeof(npath), "%s/%s", file, d->d_name);
- read_portage_env_file(configroot, npath, vars);
+ read_portage_env_file(npath, vars);
}
scandir_free(dents, dentslen);
goto done;
}
- fp = fopen(buf, "r");
+ fp = fopen(file, "r");
if (fp == NULL)
goto done;
line = 0;
while (getline(&buf, &buflen, fp) != -1) {
- ++line;
+ line++;
rmspace(buf);
if (*buf == '#' || *buf == '\0')
continue;
/* Handle "source" keyword */
- if (!strncmp(buf, "source ", 7)) {
+ if (strncmp(buf, "source ", 7) == 0) {
const char *sfile = buf + 7;
+ char npath[_Q_PATH_MAX * 2];
if (sfile[0] != '/') {
/* handle relative paths */
- size_t file_path_len, source_len;
+ size_t file_path_len;
s = strrchr(file, '/');
file_path_len = s - file + 1;
- source_len = strlen(sfile);
-
- if (buflen <= source_len + file_path_len)
- buf = xrealloc(buf,
- buflen = source_len + file_path_len + 1);
- memmove(buf + file_path_len, buf + 7, source_len + 1);
- memcpy(buf, file, file_path_len);
- sfile = buf;
+
+ snprintf(npath, sizeof(npath), "%.*s/%s",
+ (int)file_path_len, file, sfile);
+ sfile = npath;
}
- read_portage_env_file(configroot, sfile, vars);
+ read_portage_env_file(sfile, vars);
continue;
}
@@ -506,7 +423,8 @@ read_portage_env_file(const char *configroot, const char *file, env_vars vars[])
if (strncmp(buf, vars[i].name, vars[i].name_len))
continue;
- /* make sure we handle spaces between the varname, the =, and the value:
+ /* make sure we handle spaces between the varname, the =,
+ * and the value:
* VAR=val VAR = val VAR="val"
*/
s = buf + vars[i].name_len;
@@ -541,7 +459,8 @@ read_portage_env_file(const char *configroot, const char *file, env_vars vars[])
free(abuf);
if (!endq)
- warn("%s:%zu: %s: quote mismatch", file, line, vars[i].name);
+ warn("%s:%zu: %s: quote mismatch",
+ file, line, vars[i].name);
s = buf + vars[i].name_len + 2;
} else {
@@ -554,7 +473,7 @@ read_portage_env_file(const char *configroot, const char *file, env_vars vars[])
s[off] = '\0';
}
- set_portage_env_var(&vars[i], s);
+ set_portage_env_var(&vars[i], s, file);
}
}
@@ -565,47 +484,74 @@ read_portage_env_file(const char *configroot, const char *file, env_vars vars[])
/* Helper to recursively read stacked make.defaults in profiles */
static void
-read_portage_profile(const char *configroot, const char *profile, env_vars vars[])
+read_portage_profile(const char *profile, env_vars vars[])
{
- size_t configroot_len, profile_len, sub_len;
- char *profile_file, *sub_file;
+ char profile_file[_Q_PATH_MAX * 3];
+ size_t profile_len;
char *s;
+ char *p;
char *buf = NULL;
size_t buf_len = 0;
char *saveptr;
if (getenv("DEBUG"))
- fprintf(stderr, "profile %s/%s\n", configroot, profile);
+ fprintf(stderr, "profile %s\n", profile);
- /* initialize the base profile path */
- configroot_len = strlen(configroot);
- profile_len = strlen(profile);
- sub_len = 1024; /* should be big enough for longest line in "parent" */
- profile_file = xmalloc(configroot_len + profile_len + sub_len + 2);
+ /* create mutable/appendable copy */
+ profile_len = snprintf(profile_file, sizeof(profile_file), "%s/", profile);
- memcpy(profile_file, configroot, configroot_len);
- memcpy(profile_file + configroot_len, profile, profile_len);
- sub_file = profile_file + configroot_len + profile_len + 1;
- sub_file[-1] = '/';
+ /* check if we have enough space (should always be the case) */
+ if (sizeof(profile_file) - profile_len < sizeof("make.defaults"))
+ return;
/* first consume the profile's make.defaults */
- strcpy(sub_file, "make.defaults");
- read_portage_env_file("", profile_file, vars);
+ strcpy(profile_file + profile_len, "make.defaults");
+ read_portage_env_file(profile_file, vars);
/* now walk all the parents */
- strcpy(sub_file, "parent");
+ strcpy(profile_file + profile_len, "parent");
if (eat_file(profile_file, &buf, &buf_len) == 0)
- goto done;
+ return;
s = strtok_r(buf, "\n", &saveptr);
while (s) {
- strncpy(sub_file, s, sub_len);
- read_portage_profile("", profile_file, vars);
+ /* handle repo: notation (not in PMS, referenced in Wiki only?) */
+ if ((p = strchr(s, ':')) != NULL) {
+ char *overlay;
+ char *repo_name;
+ size_t n;
+
+ /* split repo from target */
+ *p++ = '\0';
+
+ /* match the repo */
+ repo_name = NULL;
+ array_for_each(overlays, n, overlay) {
+ repo_name = xarrayget(overlay_names, n);
+ if (strcmp(repo_name, s) == 0) {
+ snprintf(profile_file, sizeof(profile_file),
+ "%s/profiles/%s/", overlay, p);
+ break;
+ }
+ repo_name = NULL;
+ }
+ if (repo_name == NULL) {
+ warn("ignoring parent with unknown repo in profile: %s", s);
+ s = strtok_r(NULL, "\n", &saveptr);
+ continue;
+ }
+ } else {
+ snprintf(profile_file + profile_len,
+ sizeof(profile_file) - profile_len, "%s", s);
+ }
+ read_portage_profile(profile_file, vars);
+ /* restore original path in case we were repointed by profile */
+ if (p != NULL)
+ snprintf(profile_file, sizeof(profile_file), "%s/", profile);
s = strtok_r(NULL, "\n", &saveptr);
}
- done:
- free(profile_file);
+ free(buf);
}
static bool nocolor = 0;
@@ -618,6 +564,7 @@ env_vars vars_to_read[] = {
set, \
lset, \
.default_value = d, \
+ .src = NULL, \
},
#define _Q_EVS(t, V, v, d) _Q_EV(t, V, .value.s = &v, .value_len = strlen(d), d)
#define _Q_EVB(t, V, v, d) _Q_EV(t, V, .value.b = &v, .value_len = 0, d)
@@ -639,45 +586,176 @@ env_vars vars_to_read[] = {
_Q_EVS(STR, PKGDIR, pkgdir, CONFIG_EPREFIX "var/cache/binpkgs/")
_Q_EVS(STR, Q_VDB, portvdb, CONFIG_EPREFIX "var/db/pkg")
_Q_EVS(STR, Q_EDB, portedb, CONFIG_EPREFIX "var/cache/edb")
- { NULL, 0, _Q_BOOL, { NULL }, 0, NULL, }
+ { NULL, 0, _Q_BOOL, { NULL }, 0, NULL, NULL, }
#undef _Q_EV
};
+/* Handle a single file in the repos.conf format. */
+static void
+read_one_repos_conf(const char *repos_conf)
+{
+ int nsec;
+ char *conf;
+ const char *main_repo, *repo, *path;
+ dictionary *dict;
+
+ if (getenv("DEBUG"))
+ fprintf(stderr, " parse %s\n", repos_conf);
+
+ dict = iniparser_load(repos_conf);
+
+ main_repo = iniparser_getstring(dict, "DEFAULT:main-repo", NULL);
+
+ nsec = iniparser_getnsec(dict);
+ while (nsec-- > 0) {
+ repo = iniparser_getsecname(dict, nsec);
+ if (!strcmp(repo, "DEFAULT"))
+ continue;
+
+ xasprintf(&conf, "%s:location", repo);
+ path = iniparser_getstring(dict, conf, NULL);
+ if (path) {
+ void *ele = xarraypush_str(overlays, path);
+ xarraypush_str(overlay_names, repo);
+ xarraypush_str(overlay_src, repos_conf);
+ if (main_repo && !strcmp(repo, main_repo)) {
+ main_overlay = ele;
+ set_portage_env_var(&vars_to_read[11] /* PORTDIR */,
+ main_overlay, repos_conf);
+ }
+ }
+ free(conf);
+ }
+
+ iniparser_freedict(dict);
+}
+
+/* Handle a possible directory of files. */
+static void
+read_repos_conf(const char *configroot, const char *repos_conf)
+{
+ char *top_conf, *sub_conf;
+ int i, count;
+ struct dirent **confs;
+
+ xasprintf(&top_conf, "%s%s", configroot, repos_conf);
+ if (getenv("DEBUG"))
+ fprintf(stderr, "repos.conf.d scanner %s\n", top_conf);
+ count = scandir(top_conf, &confs, NULL, alphasort);
+ if (count == -1) {
+ if (errno == ENOTDIR)
+ read_one_repos_conf(top_conf);
+ } else {
+ for (i = 0; i < count; ++i) {
+ const char *name = confs[i]->d_name;
+
+ if (name[0] == '.' || name[0] == '\0')
+ continue;
+
+ /* Exclude backup files (aka files with ~ as postfix). */
+ if (name[strlen(name) - 1] == '~')
+ continue;
+
+#ifdef DT_UNKNOWN
+ if (confs[i]->d_type != DT_UNKNOWN &&
+ confs[i]->d_type != DT_REG &&
+ confs[i]->d_type != DT_LNK)
+ continue;
+#endif
+
+ xasprintf(&sub_conf, "%s/%s", top_conf, name);
+
+#ifdef DT_UNKNOWN
+ if (confs[i]->d_type != DT_REG)
+#endif
+ {
+ struct stat st;
+ if (stat(sub_conf, &st) || !S_ISREG(st.st_mode)) {
+ free(sub_conf);
+ continue;
+ }
+ }
+
+ read_one_repos_conf(sub_conf);
+ free(sub_conf);
+ }
+ scandir_free(confs, count);
+ }
+ free(top_conf);
+}
+
static void
initialize_portage_env(void)
{
size_t i;
const char *s;
env_vars *var;
+ char pathbuf[_Q_PATH_MAX];
+ const char *configroot = getenv("PORTAGE_CONFIGROOT");
+ char *orig_main_overlay = main_overlay;
/* initialize all the strings with their default value */
for (i = 0; vars_to_read[i].name; ++i) {
var = &vars_to_read[i];
if (var->type != _Q_BOOL)
*var->value.s = xstrdup(var->default_value);
+ var->src = xstrdup("built-in default");
}
/* figure out where to find our config files */
- const char *configroot = getenv("PORTAGE_CONFIGROOT");
if (!configroot)
- configroot = CONFIG_EPREFIX "/";
+ configroot = CONFIG_EPREFIX;
+
+ /* rstrip /-es */
+ i = strlen(configroot);
+ while (i > 0 && configroot[i - 1] == '/')
+ i--;
+
+ /* read overlays first so we can resolve repo references in profile
+ * parent files */
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s", (int)i, configroot);
+ read_repos_conf(pathbuf, "/usr/share/portage/config/repos.conf");
+ read_repos_conf(pathbuf, "/etc/portage/repos.conf");
+ if (orig_main_overlay != main_overlay)
+ free(orig_main_overlay);
+ if (array_cnt(overlays) == 0) {
+ xarraypush_ptr(overlays, main_overlay);
+ xarraypush_str(overlay_names, "<PORTDIR>");
+ xarraypush_str(overlay_src, "built-in default");
+ } else if (orig_main_overlay == main_overlay) {
+ /* if no explicit overlay was flagged as main, take the first one */
+ main_overlay = array_get_elem(overlays, 0);
+ set_portage_env_var(&vars_to_read[11] /* PORTDIR */, main_overlay,
+ (char *)array_get_elem(overlay_src, 0));
+ }
/* walk all the stacked profiles */
- read_portage_profile(configroot, "/etc/make.profile", vars_to_read);
- read_portage_profile(configroot, "/etc/portage/make.profile", vars_to_read);
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/make.profile",
+ (int)i, configroot);
+ read_portage_profile(pathbuf, vars_to_read);
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/portage/make.profile",
+ (int)i, configroot);
+ read_portage_profile(pathbuf, vars_to_read);
/* now read all the config files */
- read_portage_env_file("", CONFIG_EPREFIX "usr/share/portage/config/make.globals", vars_to_read);
- read_portage_env_file(configroot, "/etc/make.conf", vars_to_read);
- read_portage_env_file(configroot, "/etc/portage/make.conf", vars_to_read);
+ snprintf(pathbuf, sizeof(pathbuf),
+ "%.*s/usr/share/portage/config/make.globals",
+ (int)i, configroot);
+ read_portage_env_file(pathbuf, vars_to_read);
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/make.conf",
+ (int)i, configroot);
+ read_portage_env_file(pathbuf, vars_to_read);
+ snprintf(pathbuf, sizeof(pathbuf), "%.*s/etc/portage/make.conf",
+ (int)i, configroot);
+ read_portage_env_file(pathbuf, vars_to_read);
/* finally, check the env */
for (i = 0; vars_to_read[i].name; ++i) {
var = &vars_to_read[i];
s = getenv(var->name);
if (s != NULL)
- set_portage_env_var(var, s);
+ set_portage_env_var(var, s, var->name);
}
/* expand any nested variables e.g. PORTDIR=${EPREFIX}/usr/portage */
@@ -734,7 +812,8 @@ initialize_portage_env(void)
*svar = byte;
slen = strlen(sval);
post_len = strlen(svar + !!brace);
- *var->value.s = xrealloc(*var->value.s, pre_len + MAX(var_len, slen) + post_len + 1);
+ *var->value.s = xrealloc(*var->value.s,
+ pre_len + MAX(var_len, slen) + post_len + 1);
/*
* VAR=XxXxX (slen = 5)
@@ -758,18 +837,6 @@ initialize_portage_env(void)
portroot[var->value_len + 1] = '\0';
}
- char *orig_main_overlay = main_overlay;
- read_repos_conf(configroot, "/etc/portage/repos.conf");
- if (orig_main_overlay != main_overlay)
- free(orig_main_overlay);
- if (array_cnt(overlays) == 0) {
- xarraypush_ptr(overlays, main_overlay);
- xarraypush_str(overlay_names, "<PORTDIR>");
- } else if (orig_main_overlay == main_overlay) {
- /* if no explicit overlay was flagged as main, take the first one */
- main_overlay = array_get_elem(overlays, 0);
- }
-
if (getenv("DEBUG")) {
for (i = 0; vars_to_read[i].name; ++i) {
var = &vars_to_read[i];
diff --git a/main.h b/main.h
index 03c3bd2..98e5cbb 100644
--- a/main.h
+++ b/main.h
@@ -149,6 +149,7 @@ typedef struct {
} value;
size_t value_len;
const char *default_value;
+ char *src;
} env_vars;
extern env_vars vars_to_read[];
diff --git a/man/q.1 b/man/q.1
index 95caf56..886b00f 100644
--- a/man/q.1
+++ b/man/q.1
@@ -20,10 +20,12 @@ no longer necessary to initialise the cache at any time.
Install symlinks for applets.
.TP
\fB\-o\fR, \fB\-\-overlays\fR
-Print available overlays (read from repos.conf).
+Print available overlays (read from repos.conf). Use \fI-v\fR to
+see the source (file) where the overlay was declared.
.TP
\fB\-e\fR, \fB\-\-envvar\fR
-Print found environment variables and their values.
+Print used environment variables and found values. Use \fI-v\fR to
+see the source (file, environment) where the variable was declared.
.TP
\fB\-\-root\fR \fI<arg>\fR
Set the ROOT env var.
diff --git a/q.c b/q.c
index 2fb406f..40cdc2a 100644
--- a/q.c
+++ b/q.c
@@ -33,7 +33,7 @@ static struct option const q_long_opts[] = {
static const char * const q_opts_help[] = {
"Install symlinks for applets",
"Print available overlays (read from repos.conf)",
- "Print found environment variables and their values",
+ "Print used variables and their found values",
COMMON_OPTS_HELP
};
#define q_usage(ret) usage(ret, Q_FLAGS, q_long_opts, q_opts_help, NULL, lookup_applet_idx("q"))
@@ -179,10 +179,14 @@ int q_main(int argc, char **argv)
if (repo_name != NULL)
rmspace(repo_name);
}
- printf("%s%s%s: %s%s%s%s\n",
+ printf("%s%s%s: %s%s%s%s",
GREEN, repo_name == NULL ? "?unknown?" : repo_name,
NORM, overlay,
YELLOW, main_overlay == overlay ? " (main)" : "", NORM);
+ if (verbose)
+ printf(" [%s]\n", (char *)xarrayget(overlay_src, n));
+ else
+ printf("\n");
if (repo_name_len != 0) {
free(repo_name);
repo_name_len = 0;
@@ -210,14 +214,18 @@ int q_main(int argc, char **argv)
printf("%s%s%s=", BLUE, var->name, NORM);
switch (var->type) {
case _Q_BOOL:
- printf("%s%s%s\n",
+ printf("%s%s%s",
YELLOW, *var->value.b ? "1" : "0", NORM);
break;
case _Q_STR:
case _Q_ISTR:
- printf("%s\"%s\"%s\n", RED, *var->value.s, NORM);
+ printf("%s\"%s\"%s", RED, *var->value.s, NORM);
break;
}
+ if (verbose)
+ printf(" [%s]\n", var->src);
+ else
+ printf("\n");
}
} else {
/* single envvar printing, just output the value, like
@@ -238,6 +246,10 @@ int q_main(int argc, char **argv)
printf("%s%s%s\n", RED, *var->value.s, NORM);
break;
}
+ if (verbose)
+ printf(" [%s]\n", var->src);
+ else
+ printf("\n");
}
}