mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
sysconf: add a poudriere target
poudriere.conf is handed to sysrc(8), including the jail, tree, and set overlays poudriere(8) consults. make, src, and src-env are sub-targets over the matching make(1) files under poudriere.d. -l and -L list one path per line; -L includes overlays that do not exist yet. A bare -- ends the sub-target so the next word is a variable. Bump sysconf(8) to 2.2. Reviewed by: fuz, kfv, bcr Differential Revision: https://reviews.freebsd.org/D59943
This commit is contained in:
1 parent
439eb9c977
commit
398b29f07f
9 files changed
+1378
-28
No files matched your search
@@ -6,6 +6,7 @@ MAN= sysconf.8 \
|
||||
sysconf-generic.8 \
|
||||
sysconf-loader.8 \
|
||||
sysconf-make.8 \
|
||||
sysconf-poudriere.8 \
|
||||
sysconf-rc.8 \
|
||||
sysconf-src.8 \
|
||||
sysconf-sysctl.8 \
|
||||
@@ -16,6 +17,7 @@ SRCS= sysconf.c \
|
||||
sysconf_edit_assign.c \
|
||||
sysconf_edit_make.c \
|
||||
sysconf_edit_write.c \
|
||||
sysconf_poudriere.c \
|
||||
sysconf_print.c \
|
||||
sysconf_query_desc.c \
|
||||
sysconf_query_sysctl.c \
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
.\" Copyright (c) 2013-2026 Devin Teske <[email protected]>
|
||||
.\" Copyright (c) 2021-2026 Faraz Vahedi <[email protected]>
|
||||
.\"
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.Dd September 23, 2026
|
||||
.Dt SYSCONF-POUDRIERE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "sysconf poudriere"
|
||||
.Nd configure poudriere.conf and poudriere.d overlay files
|
||||
.Sh SYNOPSIS
|
||||
.Nm sysconf
|
||||
.Cm poudriere
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Ar sysrc_argument ...
|
||||
.Nm sysconf
|
||||
.Cm poudriere
|
||||
.Bro Cm make Ns | Ns Cm src Ns | Ns Cm src-env Brc
|
||||
.Op Fl ceFinNqsvVx
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Fl j Ar jail | Fl R Ar dir
|
||||
.Op Fl f Ar file
|
||||
.Ar name Ns Op Ns Oo +|- Oc Ns = Ns Ar value
|
||||
.Ar ...
|
||||
.Nm sysconf
|
||||
.Cm poudriere
|
||||
.Bro Cm make Ns | Ns Cm src Ns | Ns Cm src-env Brc
|
||||
.Op Fl eFnNqvV
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Fl f Ar file
|
||||
.Fl a
|
||||
.Nm sysconf
|
||||
.Cm poudriere
|
||||
.Bro Cm make Ns | Ns Cm src Ns | Ns Cm src-env Brc
|
||||
.Op Fl E
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Fl f Ar file
|
||||
.Fl l | L
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Cm poudriere
|
||||
target of
|
||||
.Xr sysconf 8
|
||||
reaches the same files
|
||||
.Xr poudriere 8
|
||||
sources.
|
||||
With no sub-target, it is the
|
||||
.Pa poudriere.conf
|
||||
collection, handed to
|
||||
.Xr sysrc 8
|
||||
as
|
||||
.Fl f
|
||||
files.
|
||||
The sub-targets are
|
||||
.Cm make ,
|
||||
.Cm src ,
|
||||
and
|
||||
.Cm src-env .
|
||||
Each is the matching
|
||||
.Xr make 1
|
||||
collection under
|
||||
.Pa poudriere.d ,
|
||||
handled by the same engine as
|
||||
.Xr sysconf-make 8 .
|
||||
.Pp
|
||||
A unique prefix of the
|
||||
.Cm poudriere
|
||||
keyword is accepted
|
||||
.Pq Ql p .
|
||||
A unique prefix of a sub-target is accepted the same way
|
||||
.Po
|
||||
.Ql m
|
||||
selects
|
||||
.Cm make ;
|
||||
.Ql s
|
||||
and
|
||||
.Ql sr
|
||||
are ambiguous between
|
||||
.Cm src
|
||||
and
|
||||
.Cm src-env
|
||||
.Pc .
|
||||
.Ss poudriere.conf
|
||||
.Pa poudriere.conf
|
||||
is
|
||||
.Xr rc.conf 5 Ns -style
|
||||
shell written by the administrator;
|
||||
poudriere never writes it.
|
||||
The default collection, sourced by every poudriere command, is in order:
|
||||
.Pa POUDRIERE_ETC/poudriere.conf
|
||||
if readable
|
||||
.Pq default Pa /usr/local/etc/poudriere.conf ,
|
||||
then
|
||||
.Pa POUDRIERED/poudriere.conf
|
||||
if readable and not the same file as the first
|
||||
.Pq default Pa POUDRIERE_ETC/poudriere.d/poudriere.conf .
|
||||
At least one of those two files must exist.
|
||||
Honor
|
||||
.Ev POUDRIERE_ETC
|
||||
and
|
||||
.Ev POUDRIERED
|
||||
when set.
|
||||
.Pp
|
||||
When a jail, ports tree, or set is given, the matching files are
|
||||
appended, in the order
|
||||
.Xr poudriere 8
|
||||
uses:
|
||||
.Bd -unfilled -offset indent
|
||||
.Pa POUDRIERED/<setname>-poudriere.conf
|
||||
.Pa POUDRIERED/<tree>-poudriere.conf
|
||||
.Pa POUDRIERED/<jailname>-poudriere.conf
|
||||
.Pa POUDRIERED/<tree>-<setname>-poudriere.conf
|
||||
.Pa POUDRIERED/<jailname>-<tree>-poudriere.conf
|
||||
.Pa POUDRIERED/<jailname>-<setname>-poudriere.conf
|
||||
.Pa POUDRIERED/<jailname>-<tree>-<setname>-poudriere.conf
|
||||
.Ed
|
||||
.Pp
|
||||
An explicit
|
||||
.Xr sysrc 8
|
||||
.Fl f
|
||||
replaces discovery.
|
||||
.Fl l
|
||||
and
|
||||
.Fl L
|
||||
are handled here and printed one path per line.
|
||||
For this
|
||||
.Pa poudriere.conf
|
||||
collection,
|
||||
.Fl l
|
||||
lists each readable file.
|
||||
.Fl L
|
||||
lists every location the given jail, tree, and set would consult,
|
||||
including overlays that do not exist yet.
|
||||
If no jail, tree, or set is given, the list is the two global
|
||||
.Pa poudriere.conf
|
||||
paths.
|
||||
.Fl E
|
||||
limits either list to files that exist.
|
||||
.Fl l
|
||||
and
|
||||
.Fl L
|
||||
take no variable names.
|
||||
Other arguments except the
|
||||
.Cm poudriere
|
||||
keyword itself are handed to
|
||||
.Xr sysrc 8
|
||||
verbatim.
|
||||
A bare
|
||||
.Ql --
|
||||
means the next word is a variable in this collection, even when that
|
||||
word is
|
||||
.Cm make ,
|
||||
.Cm src ,
|
||||
.Cm src-env ,
|
||||
or a unique prefix of one of those sub-targets.
|
||||
.Ss make.conf, src.conf, and src-env.conf
|
||||
These live only under
|
||||
.Pa POUDRIERED
|
||||
and use
|
||||
.Xr make 1
|
||||
syntax, so they are not mixed into the
|
||||
.Pa poudriere.conf
|
||||
sysrc collection.
|
||||
.Pp
|
||||
.Cm poudriere make
|
||||
consults, in the order shown by
|
||||
.Xr poudriere 8 :
|
||||
.Bd -unfilled -offset indent
|
||||
.Pa POUDRIERED/make.conf
|
||||
.Pa POUDRIERED/<setname>-make.conf
|
||||
.Pa POUDRIERED/<tree>-make.conf
|
||||
.Pa POUDRIERED/<jailname>-make.conf
|
||||
.Pa POUDRIERED/<tree>-<setname>-make.conf
|
||||
.Pa POUDRIERED/<jailname>-<tree>-make.conf
|
||||
.Pa POUDRIERED/<jailname>-<setname>-make.conf
|
||||
.Pa POUDRIERED/<jailname>-<tree>-<setname>-make.conf
|
||||
.Ed
|
||||
.Pp
|
||||
.Fl l
|
||||
always prints the global path, even when that file does not exist:
|
||||
.Pa POUDRIERED/make.conf
|
||||
for
|
||||
.Cm make ,
|
||||
.Pa POUDRIERED/src.conf
|
||||
for
|
||||
.Cm src ,
|
||||
and
|
||||
.Pa POUDRIERED/src-env.conf
|
||||
for
|
||||
.Cm src-env .
|
||||
An overlay is printed only when the file exists.
|
||||
.Fl L
|
||||
lists every location the given jail, tree, and set would consult,
|
||||
including files that do not exist yet.
|
||||
.Cm src
|
||||
and
|
||||
.Cm src-env
|
||||
have no per-tree file, so
|
||||
.Fl Fl tree
|
||||
does not add a path to those lists.
|
||||
.Fl E
|
||||
limits either list to files that exist, so a missing global is omitted.
|
||||
On a read, a missing global is skipped and an
|
||||
overlay is consulted only when the file exists.
|
||||
Hook-plugin
|
||||
.Pa make.conf
|
||||
files are not collected.
|
||||
.Pp
|
||||
.Cm poudriere src
|
||||
follows the shorter list
|
||||
.Xr poudriere 8
|
||||
uses when building jails
|
||||
.Pq global, then set, then jail; no tree :
|
||||
.Bd -unfilled -offset indent
|
||||
.Pa POUDRIERED/src.conf
|
||||
.Pa POUDRIERED/<setname>-src.conf
|
||||
.Pa POUDRIERED/<jailname>-src.conf
|
||||
.Ed
|
||||
.Pp
|
||||
.Cm poudriere src-env
|
||||
uses that same order, with
|
||||
.Pa src-env.conf
|
||||
in place of
|
||||
.Pa src.conf :
|
||||
.Bd -unfilled -offset indent
|
||||
.Pa POUDRIERED/src-env.conf
|
||||
.Pa POUDRIERED/<setname>-src-env.conf
|
||||
.Pa POUDRIERED/<jailname>-src-env.conf
|
||||
.Ed
|
||||
.Pp
|
||||
An explicit
|
||||
.Fl f
|
||||
replaces discovery, as on other
|
||||
.Nm sysconf
|
||||
targets.
|
||||
A name already defined is rewritten in the last file in the
|
||||
collection that defines it, so the change is not placed where a later
|
||||
overlay would mask it.
|
||||
A name defined nowhere is appended to the global file, and that write
|
||||
creates the global file when it is missing.
|
||||
A bare
|
||||
.Ar name
|
||||
reads, and
|
||||
.Ar name Ns = Ns Ar value
|
||||
writes, including
|
||||
.Ql +=
|
||||
and
|
||||
.Ql -= .
|
||||
Those rules are the
|
||||
.Dq Assignment syntax
|
||||
section of
|
||||
.Xr sysconf 8 .
|
||||
.Ss Context long options
|
||||
.Bl -tag -width indent
|
||||
.It Fl Fl jail Ar name
|
||||
Poudriere jail name, as in
|
||||
.Pa <jailname>-make.conf
|
||||
and the other jail files.
|
||||
.It Fl Fl ports Ar name , Fl Fl tree Ar name
|
||||
Poudriere ports tree.
|
||||
.Fl Fl tree
|
||||
is an alias of
|
||||
.Fl Fl ports ;
|
||||
when both are given, the last wins.
|
||||
A tree applies to
|
||||
.Pa poudriere.conf
|
||||
and the
|
||||
.Cm make
|
||||
sub-target.
|
||||
.Cm src
|
||||
and
|
||||
.Cm src-env
|
||||
ignore it; poudriere does not read a per-tree src file.
|
||||
.It Fl Fl set Ar name
|
||||
Poudriere set name.
|
||||
.El
|
||||
.Pp
|
||||
.Fl Fl jail Ns = Ns Ar name
|
||||
(and the same attached form for the others) is accepted.
|
||||
These long options are consumed here and never passed to
|
||||
.Xr sysrc 8
|
||||
or mistaken for
|
||||
.Nm sysconf
|
||||
operands.
|
||||
They are distinct from
|
||||
.Fl j
|
||||
on
|
||||
.Xr sysconf 8
|
||||
and
|
||||
.Xr sysrc 8 ,
|
||||
which name a running jail.
|
||||
.Ss Out of scope
|
||||
Poudriere maintains the following itself, or they are a different format:
|
||||
.Pp
|
||||
.Bl -tag -width indent -compact
|
||||
.It Pa poudriere.d/jails/ , poudriere.d/ports/
|
||||
One file per property; the whole file is the value.
|
||||
.It Pa poudriere.d/*-options/
|
||||
A
|
||||
.Ev PORT_DBDIR
|
||||
tree of per-port
|
||||
.Ql OPTIONS
|
||||
files, written by
|
||||
.Ql poudriere options
|
||||
.Pq Ql make config .
|
||||
.It Pa poudriere.d/*-blacklist
|
||||
Port origins, one per line
|
||||
.Pq with optional Ql @flavor ;
|
||||
.Ql #
|
||||
comments.
|
||||
Not
|
||||
.Ql name=value .
|
||||
.It Pa poudriere.d/hooks/
|
||||
Shell scripts, including plugin
|
||||
.Pa make.conf
|
||||
files under
|
||||
.Pa hooks/plugins/ .
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width POUDRIERE_ETC
|
||||
.It Ev POUDRIERE_ETC
|
||||
Directory containing
|
||||
.Pa poudriere.conf
|
||||
.Pq default Pa /usr/local/etc .
|
||||
.It Ev POUDRIERED
|
||||
Overlay directory
|
||||
.Pq default Pa POUDRIERE_ETC/poudriere.d .
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Dl sysconf poudriere ZPOOL=zroot
|
||||
.Dl sysconf poudriere --jail 131amd64 PARALLEL_JOBS=8
|
||||
.Dl sysconf p ZPOOL
|
||||
.Dl sysconf p -- src
|
||||
.Dl sysconf poudriere make --jail 131amd64 CFLAGS
|
||||
.Dl sysconf p m --jail 131amd64 CFLAGS+=-O2
|
||||
.Dl sysconf poudriere src --set dev WITHOUT_LLVM_BINUTILS=
|
||||
.Dl sysconf p src-env --jail 131amd64 SRC_ENV_VAR
|
||||
.Sh SEE ALSO
|
||||
.Xr poudriere 8 ,
|
||||
.Xr sysconf 8 ,
|
||||
.Xr sysconf-make 8 ,
|
||||
.Xr sysconf-rc 8 ,
|
||||
.Xr sysrc 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm sysconf
|
||||
utility first appeared in
|
||||
.Fx 16.0 .
|
||||
.Sh AUTHORS
|
||||
.An Devin Teske Aq Mt [email protected]
|
||||
.An Faraz Vahedi Aq Mt [email protected]
|
||||
@@ -3,7 +3,7 @@
|
||||
.\"
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.Dd August 2, 2026
|
||||
.Dd September 22, 2026
|
||||
.Dt SYSCONF-TARGETS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -24,6 +24,7 @@ Per-target file lists and syntax quirks are in
|
||||
.Xr sysconf-make 8 ,
|
||||
.Xr sysconf-src 8 ,
|
||||
.Xr sysconf-rc 8 ,
|
||||
.Xr sysconf-poudriere 8 ,
|
||||
and
|
||||
.Xr sysconf-generic 8 .
|
||||
Shared options remain in
|
||||
@@ -160,6 +161,7 @@ but may differ when the value depends on conditionals or mk defaults.
|
||||
.Xr sysconf-generic 8 ,
|
||||
.Xr sysconf-loader 8 ,
|
||||
.Xr sysconf-make 8 ,
|
||||
.Xr sysconf-poudriere 8 ,
|
||||
.Xr sysconf-rc 8 ,
|
||||
.Xr sysconf-src 8 ,
|
||||
.Xr sysconf-sysctl 8
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Target keyword selection: unique-prefix match, and the rc pass-through.
|
||||
* Target keyword selection: unique-prefix match, the rc pass-through,
|
||||
* and the poudriere target (sysrc collection or native make overlays).
|
||||
*/
|
||||
|
||||
#include "sysconf_priv.h"
|
||||
@@ -20,6 +21,7 @@ static const char *const target_keywords[] = {
|
||||
"generic",
|
||||
"loader",
|
||||
"make",
|
||||
"poudriere",
|
||||
"rc",
|
||||
"src",
|
||||
"sysctl",
|
||||
@@ -82,31 +84,47 @@ resolve_target_keyword(const char *token)
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate the target keyword in `argv' without consuming or validating
|
||||
* anything: the first argument that is neither an option cluster nor the
|
||||
* argument of one (per OPTSTRING; an unknown option letter is assumed to
|
||||
* take no argument). A `--' ends option scanning as usual. Returns the
|
||||
* argv index of the target, or -1 when there is none. Used before any
|
||||
* getopt(3) processing so that the `rc' pass-through target (see
|
||||
* exec_sysrc() below) can be detected while the command line is still
|
||||
* pristine.
|
||||
* Locate an operand in `argv' without consuming or validating anything:
|
||||
* the first argument that is neither an option cluster nor the argument
|
||||
* of one (per OPTSTRING; an unknown option letter is assumed to take no
|
||||
* argument). Used before any getopt(3) processing so that pass-through
|
||||
* targets (`rc', `poudriere'; see exec_sysrc() / poudriere_dispatch())
|
||||
* can be detected while the command line is still pristine.
|
||||
*
|
||||
* Attached arguments (`-fPATH', `-R/altroot') are self-contained: the rest
|
||||
* of the cluster is the option's argument, so the following argv element is
|
||||
* not consumed. Only a trailing option letter that takes an argument and
|
||||
* has nothing after it in the cluster (`-f PATH') skips the next element.
|
||||
*
|
||||
* Poudriere context long options (`--jail'/`--ports'/`--tree'/`--set')
|
||||
* take an argument and must not be mistaken for a keyword.
|
||||
*
|
||||
* `past_dd' is for the top-level target: `--' ends options and the next
|
||||
* word is the keyword (`sysconf -- loader'). The poudriere nested keyword
|
||||
* passes zero: `--' ends the stem, and the following word is a name
|
||||
* (`sysconf p -- src' reads the variable src from poudriere.conf).
|
||||
*/
|
||||
static int
|
||||
find_target(int argc, char *argv[])
|
||||
int
|
||||
find_operand(int argc, char *argv[], int from, int past_dd)
|
||||
{
|
||||
int n;
|
||||
const char *o;
|
||||
const char *p;
|
||||
|
||||
for (n = 1; n < argc; n++) {
|
||||
if (strcmp(argv[n], "--") == 0)
|
||||
for (n = from; n < argc; n++) {
|
||||
if (strcmp(argv[n], "--") == 0) {
|
||||
if (!past_dd)
|
||||
return (-1);
|
||||
return (n + 1 < argc ? n + 1 : -1);
|
||||
}
|
||||
if (argv[n][0] == '-' && argv[n][1] != '\0') {
|
||||
if (argv[n][1] == '-') {
|
||||
if (poudriere_longopt_p(argv[n]) &&
|
||||
strchr(argv[n], '=') == NULL &&
|
||||
n + 1 < argc)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
for (p = argv[n] + 1; *p != '\0'; p++) {
|
||||
o = strchr(OPTSTRING, *p);
|
||||
if (o != NULL && o[1] == ':') {
|
||||
@@ -129,6 +147,13 @@ find_target(int argc, char *argv[])
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
find_target(int argc, char *argv[])
|
||||
{
|
||||
|
||||
return (find_operand(argc, argv, 1, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* The `rc' pass-through: rc.conf(5) is sysrc(8)'s domain, and its feature
|
||||
* set is a superset of ours, so no option or argument is validated,
|
||||
@@ -159,21 +184,28 @@ exec_sysrc(int argc, char *argv[], int skip)
|
||||
|
||||
/*
|
||||
* Resolve the target keyword. The `rc' target execs sysrc(8) and does
|
||||
* not return, so `--help' and `--version' are not intercepted on that
|
||||
* path. Unique-prefix shorthands are expanded (`r', `m'). Returns the
|
||||
* canonical keyword, or NULL when the token is unknown or absent.
|
||||
* not return. The `poudriere' target either execs sysrc(8) or compacts
|
||||
* argv for a native make/src/src-env overlay (`*argcp' is updated) and
|
||||
* returns NULL so main does not treat it as a libbsdconf keyword.
|
||||
* Unique-prefix shorthands are expanded (`r', `m', `p'). Returns the
|
||||
* canonical keyword, or NULL when the token is unknown, absent, or
|
||||
* handled as a poudriere overlay.
|
||||
*/
|
||||
const char *
|
||||
target_resolve(int argc, char *argv[])
|
||||
target_resolve(int *argcp, char *argv[])
|
||||
{
|
||||
const char *resolved;
|
||||
int n;
|
||||
|
||||
n = find_target(argc, argv);
|
||||
n = find_target(*argcp, argv);
|
||||
if (n < 0)
|
||||
return (NULL);
|
||||
resolved = resolve_target_keyword(argv[n]);
|
||||
if (resolved != NULL && strcmp(resolved, "rc") == 0)
|
||||
exec_sysrc(argc, argv, n); /* never returns */
|
||||
exec_sysrc(*argcp, argv, n); /* never returns */
|
||||
if (resolved != NULL && strcmp(resolved, "poudriere") == 0) {
|
||||
*argcp = poudriere_dispatch(*argcp, argv, n);
|
||||
return (NULL);
|
||||
}
|
||||
return (resolved);
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
.\"
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.Dd September 22, 2026
|
||||
.Dd September 23, 2026
|
||||
.Dt SYSCONF 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -38,6 +38,45 @@
|
||||
.Nm
|
||||
.Cm rc
|
||||
.Op Ar sysrc_argument ...
|
||||
.Nm
|
||||
.Cm poudriere
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Ar sysrc_argument ...
|
||||
.Nm
|
||||
.Cm poudriere
|
||||
.Bro Cm make Ns | Ns Cm src Ns | Ns Cm src-env Brc
|
||||
.Op Fl ceFinNqsvVx
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Fl j Ar jail | Fl R Ar dir
|
||||
.Op Fl f Ar file
|
||||
.Ar name Ns Op Ns Oo +|- Oc Ns = Ns Ar value
|
||||
.Ar ...
|
||||
.Nm
|
||||
.Cm poudriere
|
||||
.Bro Cm make Ns | Ns Cm src Ns | Ns Cm src-env Brc
|
||||
.Op Fl eFnNqvV
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Fl f Ar file
|
||||
.Fl a
|
||||
.Nm
|
||||
.Cm poudriere
|
||||
.Bro Cm make Ns | Ns Cm src Ns | Ns Cm src-env Brc
|
||||
.Op Fl E
|
||||
.Op Fl Fl jail Ar name
|
||||
.Op Fl Fl ports Ar name
|
||||
.Op Fl Fl tree Ar name
|
||||
.Op Fl Fl set Ar name
|
||||
.Op Fl f Ar file
|
||||
.Fl l | L
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
@@ -259,6 +298,20 @@ Pass-through to
|
||||
.Xr sysrc 8 .
|
||||
See
|
||||
.Xr sysconf-rc 8 .
|
||||
.It Cm poudriere
|
||||
.Pa poudriere.conf
|
||||
collection via
|
||||
.Xr sysrc 8 ;
|
||||
.Cm poudriere make ,
|
||||
.Cm poudriere src ,
|
||||
and
|
||||
.Cm poudriere src-env
|
||||
for the
|
||||
.Xr make 1
|
||||
overlays under
|
||||
.Pa poudriere.d .
|
||||
See
|
||||
.Xr sysconf-poudriere 8 .
|
||||
.It Cm generic
|
||||
Foreign or unknown format;
|
||||
requires
|
||||
@@ -682,6 +735,7 @@ Further examples for each target appear in
|
||||
.Xr sysconf-make 8 ,
|
||||
.Xr sysconf-src 8 ,
|
||||
.Xr sysconf-rc 8 ,
|
||||
.Xr sysconf-poudriere 8 ,
|
||||
and
|
||||
.Xr sysconf-generic 8 .
|
||||
.Sh SEE ALSO
|
||||
@@ -695,6 +749,7 @@ and
|
||||
.Xr sysconf-generic 8 ,
|
||||
.Xr sysconf-loader 8 ,
|
||||
.Xr sysconf-make 8 ,
|
||||
.Xr sysconf-poudriere 8 ,
|
||||
.Xr sysconf-rc 8 ,
|
||||
.Xr sysconf-src 8 ,
|
||||
.Xr sysconf-sysctl 8 ,
|
||||
|
||||
@@ -171,10 +171,10 @@ main(int argc, char *argv[])
|
||||
pgm = getprogname();
|
||||
|
||||
/*
|
||||
* Target selection, including the rc pass-through, runs while
|
||||
* argv is still pristine (see target_resolve()).
|
||||
* Target selection, including the rc and poudriere pass-throughs,
|
||||
* runs while argv is still pristine (see target_resolve()).
|
||||
*/
|
||||
resolved = target_resolve(argc, argv);
|
||||
resolved = target_resolve(&argc, argv);
|
||||
|
||||
/*
|
||||
* Honor `--help' and `--version' wherever they appear (getopt(3)
|
||||
@@ -206,8 +206,11 @@ main(int argc, char *argv[])
|
||||
* sysctl(8) (e.g., `sysconf sysctl -L'). getopt(3) skips over its
|
||||
* first argument, so hand it the target keyword's slot as the
|
||||
* program name.
|
||||
*
|
||||
* Nested `poudriere make|src|src-env' already stripped both keywords;
|
||||
* remaining argv is options plus names.
|
||||
*/
|
||||
if (argc > 0) {
|
||||
if (argc > 0 && !poudriere_native()) {
|
||||
target = resolved != NULL ? resolved : argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
@@ -254,7 +257,10 @@ main(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
/* Resolve the target format and its backing files */
|
||||
resolve_target(target);
|
||||
if (poudriere_native())
|
||||
poudriere_setup();
|
||||
else
|
||||
resolve_target(target);
|
||||
|
||||
/* `-k' requires a target with a module drop-in directory */
|
||||
if (module != NULL) {
|
||||
@@ -564,6 +570,7 @@ usage(void)
|
||||
" -l | -L\n", pgm);
|
||||
fprintf(stderr,
|
||||
" %s rc [sysrc(8) argument ...]\n", pgm);
|
||||
poudriere_usage();
|
||||
fprintf(stderr, "Try `%s --help' for more information.\n", pgm);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
@@ -598,6 +605,7 @@ help(void)
|
||||
"__MAKE_CONF, SRCCONF)");
|
||||
fprintf(stderr, TGTFMT, "rc",
|
||||
"pass-through: all other arguments go to sysrc(8) verbatim");
|
||||
poudriere_help();
|
||||
fprintf(stderr, TGTFMT, "generic",
|
||||
"no default files; requires -f file");
|
||||
fprintf(stderr,
|
||||
|
||||
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2026 Devin Teske <dteske@FreeBSD.org>
|
||||
* Copyright (c) 2021-2026 Faraz Vahedi <kfv@FreeBSD.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* poudriere(8) target: poudriere.conf via sysrc(8), and the make(1)
|
||||
* overlays (make.conf, src.conf, src-env.conf) under poudriere.d.
|
||||
*/
|
||||
|
||||
#include "sysconf_priv.h"
|
||||
|
||||
#define POUDRIERE_ETC_DEF "/usr/local/etc"
|
||||
#define POUDRIERE_MAXFILES 16
|
||||
|
||||
/*
|
||||
* Nested poudriere targets (make(1) overlay files under poudriere.d).
|
||||
* Exact match wins; otherwise a unique prefix. `s' and `sr' are
|
||||
* ambiguous (src vs src-env); `m' uniquely selects make.
|
||||
*/
|
||||
static const char *const poudriere_subs[] = {
|
||||
"make",
|
||||
"src",
|
||||
"src-env",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* Poudriere context; filled when the poudriere target is selected. */
|
||||
static const char *poudriere_sub = NULL; /* make, src, src-env */
|
||||
static const char *poudriere_jail = NULL;
|
||||
static const char *poudriere_tree = NULL; /* --ports or --tree */
|
||||
static const char *poudriere_set = NULL;
|
||||
|
||||
/*
|
||||
* True when `arg' is `--name' or `--name=value'.
|
||||
*/
|
||||
static int
|
||||
longopt_eq(const char *arg, const char *name)
|
||||
{
|
||||
size_t nlen;
|
||||
|
||||
if (arg[0] != '-' || arg[1] != '-')
|
||||
return (0);
|
||||
nlen = strlen(name);
|
||||
if (strncmp(arg + 2, name, nlen) != 0)
|
||||
return (0);
|
||||
return (arg[2 + nlen] == '\0' || arg[2 + nlen] == '=');
|
||||
}
|
||||
|
||||
int
|
||||
poudriere_longopt_p(const char *arg)
|
||||
{
|
||||
|
||||
return (longopt_eq(arg, "jail") || longopt_eq(arg, "ports") ||
|
||||
longopt_eq(arg, "tree") || longopt_eq(arg, "set"));
|
||||
}
|
||||
|
||||
static void
|
||||
poudriere_add_path(char **files, unsigned int *nfiles, unsigned int max,
|
||||
const char *path)
|
||||
{
|
||||
|
||||
if (*nfiles >= max)
|
||||
errx(EXIT_FAILURE, "too many poudriere files");
|
||||
if ((files[*nfiles] = strdup(path)) == NULL)
|
||||
err(EXIT_FAILURE, NULL);
|
||||
(*nfiles)++;
|
||||
}
|
||||
|
||||
static void
|
||||
poudriere_add_if_readable(char **files, unsigned int *nfiles,
|
||||
unsigned int max, const char *path)
|
||||
{
|
||||
|
||||
if (access(path, R_OK) != 0)
|
||||
return;
|
||||
poudriere_add_path(files, nfiles, max, path);
|
||||
}
|
||||
|
||||
static int
|
||||
same_realpath(const char *a, const char *b)
|
||||
{
|
||||
char ra[PATH_MAX];
|
||||
char rb[PATH_MAX];
|
||||
|
||||
if (realpath(a, ra) == NULL || realpath(b, rb) == NULL)
|
||||
return (0);
|
||||
return (strcmp(ra, rb) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Join `dir'/`name', then prefix `-R dir' when set. `rootdir' is empty
|
||||
* until parse_options(), so the sysrc pass-through is unprefixed.
|
||||
*/
|
||||
static void
|
||||
poudriere_join(char *dst, size_t dstsz, const char *dir, const char *name)
|
||||
{
|
||||
char raw[PATH_MAX];
|
||||
int n;
|
||||
|
||||
n = snprintf(raw, sizeof(raw), "%s/%s", dir, name);
|
||||
if (n < 0 || (size_t)n >= sizeof(raw))
|
||||
errx(EXIT_FAILURE, "%s/%s: %s", dir, name,
|
||||
strerror(ENAMETOOLONG));
|
||||
n = snprintf(dst, dstsz, "%s%s", rootdir, raw);
|
||||
if (n < 0 || (size_t)n >= dstsz)
|
||||
errx(EXIT_FAILURE, "%s%s: %s", rootdir, raw,
|
||||
strerror(ENAMETOOLONG));
|
||||
}
|
||||
|
||||
static void
|
||||
poudriere_etc_d(const char **etc, const char **d, char *dbuf, size_t dbufsz)
|
||||
{
|
||||
|
||||
*etc = getenv("POUDRIERE_ETC");
|
||||
if (*etc == NULL || **etc == '\0')
|
||||
*etc = POUDRIERE_ETC_DEF;
|
||||
*d = getenv("POUDRIERED");
|
||||
if (*d == NULL || **d == '\0') {
|
||||
if (snprintf(dbuf, dbufsz, "%s/poudriere.d", *etc) >=
|
||||
(int)dbufsz)
|
||||
errx(EXIT_FAILURE, "%s/poudriere.d: %s", *etc,
|
||||
strerror(ENAMETOOLONG));
|
||||
*d = dbuf;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
poudriere_try_named(char **files, unsigned int *nfiles, unsigned int max,
|
||||
const char *dir, const char *stem, const char *suffix, int only_readable)
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
int n;
|
||||
|
||||
if (stem == NULL || *stem == '\0')
|
||||
return;
|
||||
n = snprintf(name, sizeof(name), "%s-%s", stem, suffix);
|
||||
if (n < 0 || (size_t)n >= sizeof(name))
|
||||
errx(EXIT_FAILURE, "poudriere overlay name: %s",
|
||||
strerror(ENAMETOOLONG));
|
||||
poudriere_join(path, sizeof(path), dir, name);
|
||||
if (only_readable)
|
||||
poudriere_add_if_readable(files, nfiles, max, path);
|
||||
else
|
||||
poudriere_add_path(files, nfiles, max, path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Overlay stems in poudriere(8) construction order. `full' is the
|
||||
* make.conf / poudriere.conf set (set, tree, jail, and the four combos).
|
||||
* src.conf and src-env.conf are global plus set and jail only.
|
||||
*/
|
||||
static void
|
||||
poudriere_add_overlays(char **files, unsigned int *nfiles, unsigned int max,
|
||||
const char *dir, const char *suffix, int full, int only_readable)
|
||||
{
|
||||
char stem[PATH_MAX];
|
||||
int n;
|
||||
|
||||
poudriere_try_named(files, nfiles, max, dir, poudriere_set, suffix,
|
||||
only_readable);
|
||||
if (full)
|
||||
poudriere_try_named(files, nfiles, max, dir, poudriere_tree,
|
||||
suffix, only_readable);
|
||||
poudriere_try_named(files, nfiles, max, dir, poudriere_jail, suffix,
|
||||
only_readable);
|
||||
if (!full)
|
||||
return;
|
||||
if (poudriere_tree != NULL && *poudriere_tree != '\0' &&
|
||||
poudriere_set != NULL && *poudriere_set != '\0') {
|
||||
n = snprintf(stem, sizeof(stem), "%s-%s", poudriere_tree,
|
||||
poudriere_set);
|
||||
if (n < 0 || (size_t)n >= sizeof(stem))
|
||||
errx(EXIT_FAILURE, "poudriere overlay name: %s",
|
||||
strerror(ENAMETOOLONG));
|
||||
poudriere_try_named(files, nfiles, max, dir, stem, suffix,
|
||||
only_readable);
|
||||
}
|
||||
if (poudriere_jail != NULL && *poudriere_jail != '\0' &&
|
||||
poudriere_tree != NULL && *poudriere_tree != '\0') {
|
||||
n = snprintf(stem, sizeof(stem), "%s-%s", poudriere_jail,
|
||||
poudriere_tree);
|
||||
if (n < 0 || (size_t)n >= sizeof(stem))
|
||||
errx(EXIT_FAILURE, "poudriere overlay name: %s",
|
||||
strerror(ENAMETOOLONG));
|
||||
poudriere_try_named(files, nfiles, max, dir, stem, suffix,
|
||||
only_readable);
|
||||
}
|
||||
if (poudriere_jail != NULL && *poudriere_jail != '\0' &&
|
||||
poudriere_set != NULL && *poudriere_set != '\0') {
|
||||
n = snprintf(stem, sizeof(stem), "%s-%s", poudriere_jail,
|
||||
poudriere_set);
|
||||
if (n < 0 || (size_t)n >= sizeof(stem))
|
||||
errx(EXIT_FAILURE, "poudriere overlay name: %s",
|
||||
strerror(ENAMETOOLONG));
|
||||
poudriere_try_named(files, nfiles, max, dir, stem, suffix,
|
||||
only_readable);
|
||||
}
|
||||
if (poudriere_jail != NULL && *poudriere_jail != '\0' &&
|
||||
poudriere_tree != NULL && *poudriere_tree != '\0' &&
|
||||
poudriere_set != NULL && *poudriere_set != '\0') {
|
||||
n = snprintf(stem, sizeof(stem), "%s-%s-%s", poudriere_jail,
|
||||
poudriere_tree, poudriere_set);
|
||||
if (n < 0 || (size_t)n >= sizeof(stem))
|
||||
errx(EXIT_FAILURE, "poudriere overlay name: %s",
|
||||
strerror(ENAMETOOLONG));
|
||||
poudriere_try_named(files, nfiles, max, dir, stem, suffix,
|
||||
only_readable);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the poudriere.conf collection in include_poudriere_confs() order:
|
||||
* POUDRIERE_ETC/poudriere.conf, then POUDRIERED/poudriere.conf if distinct,
|
||||
* then optional set/tree/jail overlays. At least one global file must exist.
|
||||
*/
|
||||
static void
|
||||
poudriere_collect_files(char **files, unsigned int *nfiles, unsigned int max,
|
||||
int only_readable)
|
||||
{
|
||||
char dbuf[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
const char *d;
|
||||
const char *etc;
|
||||
|
||||
poudriere_etc_d(&etc, &d, dbuf, sizeof(dbuf));
|
||||
|
||||
poudriere_join(path, sizeof(path), etc, "poudriere.conf");
|
||||
if (only_readable)
|
||||
poudriere_add_if_readable(files, nfiles, max, path);
|
||||
else
|
||||
poudriere_add_path(files, nfiles, max, path);
|
||||
|
||||
poudriere_join(path, sizeof(path), d, "poudriere.conf");
|
||||
if (*nfiles == 0 || !same_realpath(files[0], path)) {
|
||||
if (only_readable)
|
||||
poudriere_add_if_readable(files, nfiles, max, path);
|
||||
else
|
||||
poudriere_add_path(files, nfiles, max, path);
|
||||
}
|
||||
|
||||
if (only_readable && *nfiles == 0)
|
||||
errx(EXIT_FAILURE,
|
||||
"Unable to find a readable poudriere.conf in %s or %s",
|
||||
etc, d);
|
||||
|
||||
poudriere_add_overlays(files, nfiles, max, d, "poudriere.conf", 1,
|
||||
only_readable);
|
||||
}
|
||||
|
||||
/*
|
||||
* make.conf / src.conf / src-env.conf under POUDRIERED. The global file
|
||||
* is always listed (ENOENT is tolerated on read; a write creates it).
|
||||
* Overlays are appended only when readable, unless `only_readable' is 0
|
||||
* (`-L' lists every stem, including files that do not exist yet).
|
||||
* Plugin hook make.conf is not collected.
|
||||
*/
|
||||
static void
|
||||
poudriere_collect_make_files(char **files, unsigned int *nfiles,
|
||||
unsigned int max, const char *suffix, int full, int only_readable)
|
||||
{
|
||||
char dbuf[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
const char *d;
|
||||
const char *etc;
|
||||
|
||||
poudriere_etc_d(&etc, &d, dbuf, sizeof(dbuf));
|
||||
poudriere_join(path, sizeof(path), d, suffix);
|
||||
poudriere_add_path(files, nfiles, max, path);
|
||||
poudriere_add_overlays(files, nfiles, max, d, suffix, full,
|
||||
only_readable);
|
||||
}
|
||||
|
||||
/*
|
||||
* True when remaining argv (except the target at `skip') contains sysrc(8)
|
||||
* `-f'. Clusters are scanned like getopt: `f' takes an argument, as do
|
||||
* `j', `R', and `s' (so `-qf FILE' counts and `-F' does not).
|
||||
*/
|
||||
static int
|
||||
argv_has_sysrc_f(int argc, char *argv[], int skip)
|
||||
{
|
||||
const char *p;
|
||||
int n;
|
||||
|
||||
for (n = 1; n < argc; n++) {
|
||||
if (n == skip)
|
||||
continue;
|
||||
if (strcmp(argv[n], "--") == 0)
|
||||
return (0);
|
||||
if (argv[n][0] != '-' || argv[n][1] == '\0' ||
|
||||
argv[n][1] == '-')
|
||||
continue;
|
||||
for (p = argv[n] + 1; *p != '\0'; p++) {
|
||||
if (*p == 'f')
|
||||
return (1);
|
||||
if (*p == 'j' || *p == 'R' || *p == 's') {
|
||||
if (p[1] != '\0')
|
||||
break;
|
||||
if (n + 1 < argc)
|
||||
n++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If `arg' is `--name' or `--name=value', return the value. Separate-argv
|
||||
* form consumes `next' (*consumed = 1). Missing or empty values are errors.
|
||||
*/
|
||||
static const char *
|
||||
longopt_arg(const char *arg, const char *next, int *consumed,
|
||||
const char *name)
|
||||
{
|
||||
size_t nlen;
|
||||
|
||||
*consumed = 0;
|
||||
if (!longopt_eq(arg, name))
|
||||
return (NULL);
|
||||
nlen = strlen(name);
|
||||
if (arg[2 + nlen] == '=') {
|
||||
if (arg[3 + nlen] == '\0')
|
||||
errx(EXIT_FAILURE,
|
||||
"option `--%s' requires an argument", name);
|
||||
return (arg + 3 + nlen);
|
||||
}
|
||||
if (next == NULL || *next == '\0')
|
||||
errx(EXIT_FAILURE, "option `--%s' requires an argument",
|
||||
name);
|
||||
*consumed = 1;
|
||||
return (next);
|
||||
}
|
||||
|
||||
static void
|
||||
poudriere_parse_longopts(int argc, char *argv[])
|
||||
{
|
||||
const char *next;
|
||||
const char *val;
|
||||
int consumed;
|
||||
int n;
|
||||
|
||||
for (n = 1; n < argc; n++) {
|
||||
if (strcmp(argv[n], "--") == 0)
|
||||
break;
|
||||
consumed = 0;
|
||||
next = (n + 1 < argc) ? argv[n + 1] : NULL;
|
||||
if ((val = longopt_arg(argv[n], next, &consumed,
|
||||
"jail")) != NULL)
|
||||
poudriere_jail = val;
|
||||
else if ((val = longopt_arg(argv[n], next, &consumed,
|
||||
"ports")) != NULL)
|
||||
poudriere_tree = val;
|
||||
else if ((val = longopt_arg(argv[n], next, &consumed,
|
||||
"tree")) != NULL)
|
||||
poudriere_tree = val;
|
||||
else if ((val = longopt_arg(argv[n], next, &consumed,
|
||||
"set")) != NULL)
|
||||
poudriere_set = val;
|
||||
if (consumed)
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop the poudriere keyword, optional nested target, and context long
|
||||
* options so the remainder can be parsed as a native sysconf command
|
||||
* line (or, for the sysrc path, rebuilt without those tokens).
|
||||
*/
|
||||
static int
|
||||
poudriere_compact(int argc, char *argv[], int tgt, int sub)
|
||||
{
|
||||
int dst;
|
||||
int endopts;
|
||||
int n;
|
||||
|
||||
dst = 1;
|
||||
endopts = 0;
|
||||
for (n = 1; n < argc; n++) {
|
||||
if (n == tgt || n == sub)
|
||||
continue;
|
||||
if (!endopts && strcmp(argv[n], "--") == 0)
|
||||
endopts = 1;
|
||||
if (!endopts && poudriere_longopt_p(argv[n])) {
|
||||
if (strchr(argv[n], '=') == NULL && n + 1 < argc)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
argv[dst++] = argv[n];
|
||||
}
|
||||
argv[dst] = NULL;
|
||||
return (dst);
|
||||
}
|
||||
|
||||
/*
|
||||
* `-l' / `-L' on this target. Returns 1 when either is present.
|
||||
* `*all' is `-L' (every location for the named jail, tree, and set,
|
||||
* including files that do not exist). `*exist' is `-E'. `*filep' is an
|
||||
* explicit `-f'. `*names' is a non-option operand (listing takes none).
|
||||
* `-R dir' is applied as the sysconf root for the paths printed.
|
||||
*/
|
||||
static int
|
||||
argv_wants_list(int argc, char *argv[], int skip, int *all, int *exist,
|
||||
const char **filep, int *names)
|
||||
{
|
||||
const char *arg;
|
||||
const char *p;
|
||||
int list;
|
||||
int n;
|
||||
|
||||
*all = 0;
|
||||
*exist = 0;
|
||||
*filep = NULL;
|
||||
*names = 0;
|
||||
list = 0;
|
||||
for (n = 1; n < argc; n++) {
|
||||
if (n == skip)
|
||||
continue;
|
||||
if (strcmp(argv[n], "--") == 0) {
|
||||
if (n + 1 < argc)
|
||||
*names = 1;
|
||||
break;
|
||||
}
|
||||
if (argv[n][0] == '-' && argv[n][1] == '-') {
|
||||
if (poudriere_longopt_p(argv[n]) &&
|
||||
strchr(argv[n], '=') == NULL && n + 1 < argc)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
if (argv[n][0] != '-' || argv[n][1] == '\0') {
|
||||
*names = 1;
|
||||
continue;
|
||||
}
|
||||
for (p = argv[n] + 1; *p != '\0'; p++) {
|
||||
if (*p == 'l')
|
||||
list = 1;
|
||||
else if (*p == 'L') {
|
||||
list = 1;
|
||||
*all = 1;
|
||||
} else if (*p == 'E')
|
||||
*exist = 1;
|
||||
else if (*p == 'f' || *p == 'j' || *p == 'R' ||
|
||||
*p == 's') {
|
||||
if (p[1] != '\0')
|
||||
arg = p + 1;
|
||||
else if (n + 1 < argc)
|
||||
arg = argv[++n];
|
||||
else
|
||||
arg = NULL;
|
||||
if (*p == 'f')
|
||||
*filep = arg;
|
||||
else if (*p == 'R' && arg != NULL)
|
||||
rootdir = arg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (list);
|
||||
}
|
||||
|
||||
static void
|
||||
poudriere_puts_files(char **files, unsigned int nfiles, int exist_only)
|
||||
{
|
||||
unsigned int n;
|
||||
|
||||
for (n = 0; n < nfiles; n++) {
|
||||
if (exist_only && access(files[n], F_OK) != 0)
|
||||
continue;
|
||||
puts(files[n]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The `poudriere' target without a nested make/src/src-env keyword:
|
||||
* resolve the shell-sourced poudriere.conf collection (same order as
|
||||
* poudriere's include_poudriere_confs()) and hand it to sysrc(8) as
|
||||
* `-f' files. `--jail'/`--ports'/`--tree'/`--set' select overlays;
|
||||
* they are stripped so sysrc never sees them. An explicit sysrc `-f'
|
||||
* replaces discovery. `-l' and `-L' are printed here, one path per
|
||||
* line. Never returns.
|
||||
*/
|
||||
static void
|
||||
exec_poudriere_sysrc(int argc, char *argv[], int skip)
|
||||
{
|
||||
char *files[POUDRIERE_MAXFILES];
|
||||
char **nargv;
|
||||
char path[PATH_MAX];
|
||||
const char *list_file;
|
||||
unsigned int nfiles;
|
||||
int all;
|
||||
int endopts;
|
||||
int exist;
|
||||
int n;
|
||||
int names;
|
||||
int nargc;
|
||||
int user_f;
|
||||
|
||||
nfiles = 0;
|
||||
nargc = 0;
|
||||
if (argv_wants_list(argc, argv, skip, &all, &exist, &list_file,
|
||||
&names)) {
|
||||
if (names)
|
||||
errx(EXIT_FAILURE, "-l/-L take no names");
|
||||
if (list_file != NULL) {
|
||||
if (snprintf(path, sizeof(path), "%s%s", rootdir,
|
||||
list_file) >= (int)sizeof(path))
|
||||
errx(EXIT_FAILURE, "%s%s: %s", rootdir,
|
||||
list_file, strerror(ENAMETOOLONG));
|
||||
if (!exist || access(path, F_OK) == 0)
|
||||
puts(path);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
poudriere_collect_files(files, &nfiles, POUDRIERE_MAXFILES,
|
||||
all ? 0 : 1);
|
||||
poudriere_puts_files(files, nfiles, exist);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
user_f = argv_has_sysrc_f(argc, argv, skip);
|
||||
if (!user_f)
|
||||
poudriere_collect_files(files, &nfiles, POUDRIERE_MAXFILES,
|
||||
1);
|
||||
|
||||
if ((nargv = calloc((size_t)argc + (size_t)nfiles * 2 + 2,
|
||||
sizeof(*nargv))) == NULL)
|
||||
err(EXIT_FAILURE, NULL);
|
||||
nargv[nargc++] = (char *)(uintptr_t)"sysrc";
|
||||
for (n = 0; n < (int)nfiles; n++) {
|
||||
nargv[nargc++] = (char *)(uintptr_t)"-f";
|
||||
nargv[nargc++] = files[n];
|
||||
}
|
||||
endopts = 0;
|
||||
for (n = 1; n < argc; n++) {
|
||||
if (n == skip)
|
||||
continue;
|
||||
if (!endopts && strcmp(argv[n], "--") == 0) {
|
||||
endopts = 1;
|
||||
nargv[nargc++] = argv[n];
|
||||
continue;
|
||||
}
|
||||
if (!endopts && poudriere_longopt_p(argv[n])) {
|
||||
if (strchr(argv[n], '=') == NULL && n + 1 < argc)
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
nargv[nargc++] = argv[n];
|
||||
}
|
||||
nargv[nargc] = NULL;
|
||||
|
||||
execvp("sysrc", nargv);
|
||||
err(EXIT_FAILURE, "sysrc");
|
||||
}
|
||||
|
||||
int
|
||||
poudriere_native(void)
|
||||
{
|
||||
|
||||
return (poudriere_sub != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Nested `poudriere make|src|src-env': native make(1) format over the
|
||||
* matching poudriere.d overlay collection. `-f' replaces discovery.
|
||||
*/
|
||||
void
|
||||
poudriere_setup(void)
|
||||
{
|
||||
char *files[POUDRIERE_MAXFILES];
|
||||
char path[PATH_MAX];
|
||||
const char *prefix;
|
||||
const char *suffix;
|
||||
int full;
|
||||
unsigned int i;
|
||||
unsigned int nfiles;
|
||||
|
||||
format = BSDCONF_FORMAT_MAKE;
|
||||
if (file != NULL) {
|
||||
prefix = file_stdin ? "" : rootdir;
|
||||
if ((conf_files = calloc(1, sizeof(*conf_files))) == NULL)
|
||||
err(EXIT_FAILURE, NULL);
|
||||
if (snprintf(path, sizeof(path), "%s%s", prefix, file) >=
|
||||
(int)sizeof(path))
|
||||
errx(EXIT_FAILURE, "%s%s: %s", prefix, file,
|
||||
strerror(ENAMETOOLONG));
|
||||
if ((conf_files[0] = strdup(path)) == NULL)
|
||||
err(EXIT_FAILURE, NULL);
|
||||
nconf_files = 1;
|
||||
write_idx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(poudriere_sub, "make") == 0) {
|
||||
suffix = "make.conf";
|
||||
full = 1;
|
||||
} else if (strcmp(poudriere_sub, "src") == 0) {
|
||||
suffix = "src.conf";
|
||||
full = 0;
|
||||
} else {
|
||||
suffix = "src-env.conf";
|
||||
full = 0;
|
||||
}
|
||||
|
||||
nfiles = 0;
|
||||
/* `-L' lists missing overlays; reads and `-l' do not. */
|
||||
poudriere_collect_make_files(files, &nfiles, POUDRIERE_MAXFILES,
|
||||
suffix, full, list_all ? 0 : 1);
|
||||
if ((conf_files = calloc(nfiles, sizeof(*conf_files))) == NULL)
|
||||
err(EXIT_FAILURE, NULL);
|
||||
for (i = 0; i < nfiles; i++)
|
||||
conf_files[i] = files[i];
|
||||
nconf_files = nfiles;
|
||||
write_idx = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* On the sysrc path, exec and do not return. On the native
|
||||
* make/src/src-env path, rewrite argv and return the new argc.
|
||||
* A bare `--' before the next word ends the nested keyword, so that
|
||||
* word is a poudriere.conf variable (`sysconf p -- src').
|
||||
*/
|
||||
int
|
||||
poudriere_dispatch(int argc, char *argv[], int tgt)
|
||||
{
|
||||
int subn;
|
||||
|
||||
poudriere_parse_longopts(argc, argv);
|
||||
subn = find_operand(argc, argv, tgt + 1, 0);
|
||||
if (subn > 0 && strchr(argv[subn], '=') == NULL)
|
||||
poudriere_sub = resolve_keyword(argv[subn], poudriere_subs,
|
||||
"poudriere target");
|
||||
if (poudriere_sub == NULL)
|
||||
exec_poudriere_sysrc(argc, argv, tgt); /* never returns */
|
||||
return (poudriere_compact(argc, argv, tgt, subn));
|
||||
}
|
||||
|
||||
void
|
||||
poudriere_usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
" %s poudriere [--jail name] [--ports name] [--tree name]\n",
|
||||
pgm);
|
||||
fprintf(stderr,
|
||||
" [--set name] [sysrc(8) argument ...]\n");
|
||||
fprintf(stderr,
|
||||
" %s poudriere {make|src|src-env} [-ceFinNqsvVx]\n", pgm);
|
||||
fprintf(stderr,
|
||||
" [--jail name] [--ports name] [--tree name]\n");
|
||||
fprintf(stderr,
|
||||
" [--set name] [-j jail | -R dir] [-f file]\n");
|
||||
fprintf(stderr,
|
||||
" name[[+|-]=value] ...\n");
|
||||
fprintf(stderr,
|
||||
" %s poudriere {make|src|src-env} [-eFnNqvV]\n", pgm);
|
||||
fprintf(stderr,
|
||||
" [--jail name] [--ports name] [--tree name]\n");
|
||||
fprintf(stderr,
|
||||
" [--set name] [-f file] -a\n");
|
||||
fprintf(stderr,
|
||||
" %s poudriere {make|src|src-env} [-E]\n", pgm);
|
||||
fprintf(stderr,
|
||||
" [--jail name] [--ports name] [--tree name]\n");
|
||||
fprintf(stderr,
|
||||
" [--set name] [-f file] -l | -L\n");
|
||||
}
|
||||
|
||||
void
|
||||
poudriere_help(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "\t%-9s %s\n", "poudriere",
|
||||
"poudriere.conf via sysrc(8); make/src/src-env overlays");
|
||||
fprintf(stderr, "\t%-9s %s\n", "",
|
||||
"(--jail/--ports/--tree/--set select poudriere.d files)");
|
||||
}
|
||||
@@ -37,7 +37,7 @@
|
||||
#define __unused /* not all compilers support attributes */
|
||||
#endif
|
||||
|
||||
#define SYSCONF_VERSION "2.1 2026-09-22"
|
||||
#define SYSCONF_VERSION "2.2 2026-09-22"
|
||||
|
||||
/* getopt(3) optstring; shared by parse_options() and find_target() */
|
||||
#define OPTSTRING "AacdDEeFf:hij:k:lLnNqR:svVx"
|
||||
@@ -197,12 +197,21 @@ int sysctl_writable(const char *_name, const char *_value,
|
||||
#endif
|
||||
|
||||
/* sysconf-targets.c */
|
||||
int find_operand(int _argc, char **_argv, int _from, int _past_dd);
|
||||
const char *resolve_keyword(const char *_token,
|
||||
const char *const *_keywords, const char *_what);
|
||||
const char *target_resolve(int _argc, char **_argv);
|
||||
const char *target_resolve(int *_argcp, char **_argv);
|
||||
|
||||
/* sysconf.c */
|
||||
void usage(void);
|
||||
void help(void);
|
||||
|
||||
/* sysconf_poudriere.c */
|
||||
int poudriere_longopt_p(const char *_arg);
|
||||
int poudriere_dispatch(int _argc, char **_argv, int _tgt);
|
||||
int poudriere_native(void);
|
||||
void poudriere_setup(void);
|
||||
void poudriere_usage(void);
|
||||
void poudriere_help(void);
|
||||
|
||||
#endif /* !_SYSCONF_PRIV_H_ */
|
||||
@@ -486,6 +486,205 @@ target_prefix_cleanup()
|
||||
cleanup_root
|
||||
}
|
||||
|
||||
atf_test_case poudriere_sysrc cleanup
|
||||
poudriere_sysrc_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"poudriere target feeds sysrc -f over the conf collection"
|
||||
}
|
||||
poudriere_sysrc_body()
|
||||
{
|
||||
find_sysconf
|
||||
command -v sysrc > /dev/null 2>&1 ||
|
||||
atf_skip "sysrc not installed"
|
||||
ETC="$( pwd )/petc"
|
||||
mkdir -p "$ETC/poudriere.d"
|
||||
printf 'ZPOOL=old\nFOO=global\n' > "$ETC/poudriere.conf"
|
||||
printf 'FOO=jail\nJOBS=2\n' \
|
||||
> "$ETC/poudriere.d/131amd64-poudriere.conf"
|
||||
export POUDRIERE_ETC="$ETC"
|
||||
|
||||
# -l / -L are printed here, one path per line (not sysrc -L)
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n" \
|
||||
"$SYSCONF" p -l
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n$ETC/poudriere.d/poudriere.conf\n" \
|
||||
"$SYSCONF" p -L
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n$ETC/poudriere.d/131amd64-poudriere.conf\n" \
|
||||
"$SYSCONF" p --jail 131amd64 -l
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n$ETC/poudriere.d/poudriere.conf\n$ETC/poudriere.d/131amd64-poudriere.conf\n" \
|
||||
"$SYSCONF" p --jail 131amd64 -L
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n" \
|
||||
"$SYSCONF" p --jail 99amd64 -l
|
||||
atf_check -o match:'99amd64-poudriere.conf' \
|
||||
-o not-match:'rc\.conf' \
|
||||
"$SYSCONF" p --jail 99amd64 -L
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n" \
|
||||
"$SYSCONF" p -E -L
|
||||
atf_check -o inline:"$ETC/poudriere.conf\n$ETC/poudriere.d/131amd64-poudriere.conf\n" \
|
||||
"$SYSCONF" p --jail 131amd64 -E -L
|
||||
atf_check -s not-exit:0 -e match:'take no names' \
|
||||
"$SYSCONF" p -l ZPOOL
|
||||
|
||||
# Shorthand p; read from the global file
|
||||
atf_check -o match:'ZPOOL: old' \
|
||||
"$SYSCONF" p ZPOOL
|
||||
# Write a new name into the first file
|
||||
atf_check -o match:'BASEFS' \
|
||||
"$SYSCONF" poudriere BASEFS=/poudriere
|
||||
atf_check -o match:'BASEFS=' cat "$ETC/poudriere.conf"
|
||||
atf_check -o not-match:'BASEFS' \
|
||||
cat "$ETC/poudriere.d/131amd64-poudriere.conf"
|
||||
|
||||
# Overlay collection: --jail appends the jail overlay last
|
||||
atf_check -o match:'FOO: jail' \
|
||||
"$SYSCONF" poudriere --jail 131amd64 FOO
|
||||
# Without --jail the overlay is not in the collection
|
||||
atf_check -o match:'FOO: global' \
|
||||
"$SYSCONF" poudriere FOO
|
||||
# --tree is an alias of --ports
|
||||
printf 'FOO=tree\n' > "$ETC/poudriere.d/default-poudriere.conf"
|
||||
atf_check -o match:'FOO: tree' \
|
||||
"$SYSCONF" poudriere --tree default FOO
|
||||
atf_check -o match:'FOO: tree' \
|
||||
"$SYSCONF" poudriere --ports default FOO
|
||||
# Rewrite the overlay's existing var
|
||||
atf_check -o match:'JOBS' \
|
||||
"$SYSCONF" poudriere --jail 131amd64 JOBS=8
|
||||
atf_check -o match:'JOBS: 8' \
|
||||
"$SYSCONF" poudriere --jail 131amd64 JOBS
|
||||
|
||||
# Attached --jail=
|
||||
atf_check -o match:'FOO: jail' \
|
||||
"$SYSCONF" poudriere --jail=131amd64 FOO
|
||||
|
||||
# `--' ends the nested keyword; colliding names are variables
|
||||
printf 'src=from-conf\nm=short\n' >> "$ETC/poudriere.conf"
|
||||
printf 'src=from-overlay\n' > "$ETC/poudriere.d/src.conf"
|
||||
atf_check -o match:'src: from-conf' \
|
||||
"$SYSCONF" p -- src
|
||||
atf_check -o match:'m: short' \
|
||||
"$SYSCONF" p -- m
|
||||
atf_check -s not-exit:0 -e match:"unknown variable 'make'" \
|
||||
"$SYSCONF" p -- make
|
||||
atf_check -o match:'src: from-overlay' \
|
||||
"$SYSCONF" p src src
|
||||
|
||||
# -f replaces discovery
|
||||
printf 'BAR=only\n' > "$ETC/other.conf"
|
||||
atf_check -o match:'BAR: only' \
|
||||
"$SYSCONF" poudriere -f "$ETC/other.conf" BAR
|
||||
|
||||
# Missing globals
|
||||
unset POUDRIERE_ETC
|
||||
export POUDRIERE_ETC="$( pwd )/missing-etc"
|
||||
mkdir -p "$POUDRIERE_ETC"
|
||||
atf_check -s not-exit:0 -e match:'poudriere.conf' \
|
||||
"$SYSCONF" p ZPOOL
|
||||
}
|
||||
poudriere_sysrc_cleanup()
|
||||
{
|
||||
rm -rf "$( pwd )/petc" "$( pwd )/missing-etc"
|
||||
}
|
||||
|
||||
atf_test_case poudriere_overlays cleanup
|
||||
poudriere_overlays_head()
|
||||
{
|
||||
atf_set "descr" \
|
||||
"poudriere make/src/src-env overlays with --jail/--tree/--set"
|
||||
}
|
||||
poudriere_overlays_body()
|
||||
{
|
||||
find_sysconf
|
||||
ETC="$( pwd )/petc"
|
||||
D="$ETC/poudriere.d"
|
||||
mkdir -p "$D"
|
||||
export POUDRIERE_ETC="$ETC"
|
||||
|
||||
printf 'CFLAGS=global\n' > "$D/make.conf"
|
||||
printf 'CFLAGS=jail\n' > "$D/131amd64-make.conf"
|
||||
printf 'CFLAGS=tree\n' > "$D/default-make.conf"
|
||||
printf 'CFLAGS=set\n' > "$D/dev-make.conf"
|
||||
printf 'CFLAGS=combo\n' > "$D/131amd64-default-make.conf"
|
||||
|
||||
# Shorthand p m
|
||||
atf_check -o inline:'CFLAGS: global\n' \
|
||||
"$SYSCONF" p m CFLAGS
|
||||
atf_check -o inline:'CFLAGS: jail\n' \
|
||||
"$SYSCONF" poudriere make --jail 131amd64 CFLAGS
|
||||
atf_check -o inline:'CFLAGS: tree\n' \
|
||||
"$SYSCONF" p m --tree default CFLAGS
|
||||
atf_check -o inline:'CFLAGS: tree\n' \
|
||||
"$SYSCONF" poudriere make --ports default CFLAGS
|
||||
atf_check -o inline:'CFLAGS: set\n' \
|
||||
"$SYSCONF" poudriere make --set dev CFLAGS
|
||||
# jail-tree combo is last of those two
|
||||
atf_check -o inline:'CFLAGS: combo\n' \
|
||||
"$SYSCONF" poudriere make --jail 131amd64 --tree default CFLAGS
|
||||
|
||||
# Rewrite overlay's existing name; new name goes to global
|
||||
atf_check -o match:'CFLAGS' \
|
||||
"$SYSCONF" poudriere make --jail 131amd64 CFLAGS=-O2
|
||||
atf_check -o match:'CFLAGS=-O2' cat "$D/131amd64-make.conf"
|
||||
atf_check -o match:'CFLAGS=global' cat "$D/make.conf"
|
||||
atf_check -o match:'CXXFLAGS' \
|
||||
"$SYSCONF" poudriere make --jail 131amd64 CXXFLAGS=-pipe
|
||||
atf_check -o match:'CXXFLAGS=-pipe' cat "$D/make.conf"
|
||||
atf_check -o not-match:'CXXFLAGS' cat "$D/131amd64-make.conf"
|
||||
|
||||
# Create missing global
|
||||
rm -f "$D/make.conf"
|
||||
atf_check -o match:'LDFLAGS' \
|
||||
"$SYSCONF" p m LDFLAGS=-L/usr/local/lib
|
||||
atf_check -o match:'LDFLAGS=-L/usr/local/lib' cat "$D/make.conf"
|
||||
|
||||
# src vs src-env; --tree ignored (no tree-src.conf in poudriere(8))
|
||||
printf 'WITHOUT_FOO=\n' > "$D/src.conf"
|
||||
printf 'WITHOUT_TREE=\n' > "$D/default-src.conf"
|
||||
printf 'SRC_ENV_VAR=1\n' > "$D/src-env.conf"
|
||||
printf 'SRC_ENV_VAR=tree\n' > "$D/default-src-env.conf"
|
||||
atf_check -o inline:'WITHOUT_FOO (present)\n' \
|
||||
"$SYSCONF" poudriere src WITHOUT_FOO
|
||||
atf_check -s not-exit:0 -e match:'unknown directive' \
|
||||
"$SYSCONF" poudriere src --tree default WITHOUT_TREE
|
||||
atf_check -o inline:'SRC_ENV_VAR: 1\n' \
|
||||
"$SYSCONF" poudriere src-env SRC_ENV_VAR
|
||||
atf_check -o inline:'SRC_ENV_VAR: 1\n' \
|
||||
"$SYSCONF" poudriere src-env --tree default SRC_ENV_VAR
|
||||
atf_check -o inline:'SRC_ENV_VAR: 1\n' \
|
||||
"$SYSCONF" p src-e SRC_ENV_VAR
|
||||
|
||||
# Ambiguous nested prefix
|
||||
atf_check -s not-exit:0 -e match:'ambiguous' -e match:'src' \
|
||||
-e match:'src-env' \
|
||||
"$SYSCONF" p s FOO
|
||||
|
||||
# -l lists the collection
|
||||
atf_check -o match:'make.conf' -o match:'131amd64-make.conf' \
|
||||
"$SYSCONF" poudriere make --jail 131amd64 -l
|
||||
|
||||
# -L lists every poudriere(8) stem, including files not on disk
|
||||
atf_check -o inline:"$D/make.conf\n$D/abc-make.conf\n$D/xyz-make.conf\n$D/160-make.conf\n$D/xyz-abc-make.conf\n$D/160-xyz-make.conf\n$D/160-abc-make.conf\n$D/160-xyz-abc-make.conf\n" \
|
||||
"$SYSCONF" p m --jail 160 --set abc --tree xyz -L
|
||||
atf_check -o inline:"$D/make.conf\n$D/xyz-make.conf\n$D/160-make.conf\n$D/160-xyz-make.conf\n" \
|
||||
"$SYSCONF" p m --jail 160 --tree xyz -L
|
||||
atf_check -o inline:"$D/make.conf\n" \
|
||||
"$SYSCONF" p m --jail 160 --set abc --tree xyz -l
|
||||
atf_check -o inline:"$D/make.conf\n" \
|
||||
"$SYSCONF" p m --jail 160 --set abc --tree xyz -E -L
|
||||
atf_check -o inline:"$D/src.conf\n$D/abc-src.conf\n$D/160-src.conf\n" \
|
||||
"$SYSCONF" p src --jail 160 --set abc --tree xyz -L
|
||||
atf_check -o inline:"$D/src.conf\n$D/160-src.conf\n" \
|
||||
"$SYSCONF" p src --jail 160 --tree xyz -L
|
||||
atf_check -o inline:"$D/src-env.conf\n$D/abc-src-env.conf\n$D/160-src-env.conf\n" \
|
||||
"$SYSCONF" p src-env --jail 160 --set abc --tree xyz -L
|
||||
atf_check -o inline:"$D/src-env.conf\n" \
|
||||
"$SYSCONF" p src-env --jail 160 --set abc --tree xyz -E -L
|
||||
}
|
||||
poudriere_overlays_cleanup()
|
||||
{
|
||||
rm -rf "$( pwd )/petc"
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case make_src_knobs
|
||||
@@ -500,4 +699,6 @@ atf_init_test_cases()
|
||||
atf_add_test_case sysctl_oid_range
|
||||
atf_add_test_case max_bytes_cap
|
||||
atf_add_test_case target_prefix
|
||||
atf_add_test_case poudriere_sysrc
|
||||
atf_add_test_case poudriere_overlays
|
||||
}
|
||||
Reference in new issue
Block a user