Almost all programs are simple and have only a single command. When
printing options, let's just use the first COMMAND block found by default.
This means we can drop the explicit program-name argument and reduce
copy&paste boilerplate.
The custom help() is replaced by a COMMAND() description, and
--introspect-cli is added. --help now goes through the pager, like other
commands with --no-pager.
Synopses are adjusted. --user-unit/--unit without any unit names is
technically allowed, but not very meaningful, since it's the same as
the default mode. So [] is dropped. And the prog help string is then
adjusted to match the man page.
I am really not a fan of full code lines passed to macros as parameters.
Let's get rid of the 3rd parameter of FOREACH_OPTION() hence:
1. Let's return errors just as a regular value (though a negative one),
that can be handled via a OPTION_ERROR case statement for the switch.
This normalizes handling of the error, just like any other event
returned by the option parser.
2. In order to avoid exploding the amount of boilerplate in each use
(that just propagates the error on OPTION_ERROR), let's then
introduce an explicit FOREACH_OPTION_OR_RETURN(), that returns from
the calling function on its own (and makes that clear in the name).
Together this cleans up, normalizes the logic and shortens the code.
It was requested to make the 'c', 'opt', and 'arg' params the same, i.e.
defined through the FOREACH_OPTION macro. But we can't do that easily,
because 'c' was defined in the for loop definition, and we can only
define variables of the same type in that way. Also, in some cases we
need only 'c', in other cases with need 'c' and 'arg, in some cases 'c'
and 'opt', and in other cases all three. We'd need to either
conditionalize or mark those variables with _unused_ to deal with
compiler warnings. But a different approach works quite nicely: add
state.opt and state.arg to show the current option and it's argument.
(The short names are picked on purpose to reduce verbosity since those
are used a lot.)
This is a bit tricky. Previously, the --help string said
"-x --xattr=BOOL", which normally means that '-x BOOL' and '--xattr BOOL'
and '--xattr=BOOL' are all accepted and equivalent. But actually only
the third form was accepted. '-x' should have been and is now documented
as "Same as --xattr=true". The man page tried to explain this, but not
very strongly. So update the man page to have more emphasis and restore
the special behaviour for -x and -c. This is a on old program, so I
think in this case, maintaining compatiblity in behaviour is important.
arg_names is changed to be a normal strv. In the new parser code,
the argument is returned as a const char*. Dropping the const
to stuff it into the array would be too ugly.
The metavars for optional args are now shown in --help.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Mixing the `--unit` and `--user-unit` options will result in error messages.
During the parsing phase, only the `arg_show_unit` record of the last
occurrence of the option is used; all names are placed in the same `arg_names`,
thus mixing the two types of units in the query.
For example, `-u foo --user-unit bar` will also treat `foo` as a user unit and
query it in the user service.
This commit cleans up the includes for all the small tools across
the tree.
A few cases of returning EXIT_SUCCESS are replaced with returning
0 to avoid including <stdlib.h>.
Split out of #37344.
In the documentation we usually spell the concept "control group".
Internally in code we usually call it "cgroup" or "CGroup". In systemctl output we
called the field "CGroup" so far, i.e. a capitalized version of the
internal name. This is of course very unsystematic. Let's clean this up
a bit: let's now say:
* in docs, continue to spell it out "control groups"
* in brief output call it "CGroup"
* internally call it "cgroup" or "CGroup"
Fixes: #14429
Otherwise, if getopt() and friends are used before parse_argv(), then
the GNU extensions may be ignored.
This should not change any behavior at least now, as we usually use
getopt_long() only once per invocation. But in the next commit,
getopt_long() will be used for other arrays, hence this change will
become necessary.
Those are rather specialized bits of information, useful mostly for debugging.
I use cgls quite often but never had the need to use either of those…
But they take up a significant amount of screen real estate, esp. when
executed as root:
-.slice
├─user.slice (#1683)
│ → user.invocation_id: 74b0bd1258c5485eb969016384e0d06a
│ → trusted.invocation_id: 74b0bd1258c5485eb969016384e0d06a
│ └─user-1000.slice (#6488)
│ → user.invocation_id: b0261a14fe74490d9a9d5266c52cceb6
│ → trusted.invocation_id: b0261a14fe74490d9a9d5266c52cceb6
│ ├─user@1000.service … (#6590)
│ │ → user.invocation_id: 9e1fb54ad07940d8b92c33c81d169f11
│ │ → user.delegate: 1
│ │ → trusted.invocation_id: 9e1fb54ad07940d8b92c33c81d169f11
│ │ → trusted.delegate: 1
│ │ ├─session.slice (#6874)
...
Let's not show them by default, so we can show more cgroups.
(Also, on a terminal, we already highlight delegate units via underlining and
an ellipsis, so 'user.delegate:1' is redundant.)
In various tools and services we have a per-system and per-user concept.
So far we sometimes used a boolean indicating whether we are in system
mode, or a reversed boolean indicating whether we are in user mode, or
the LookupScope enum used by the lookup path logic.
Let's address that, in introduce a common enum for this, we can use all
across the board.
This is mostly just search/replace, no actual code changes.
so the CLI interface is now similar to `systemctl`, i.e. if no unit name
suffix is provided, assume `.service`.
Fixes: #20492
Before:
```
$ systemd-cgls --unit user@1000
Failed to query unit control group path: Invalid argument
Failed to list cgroup tree: Invalid argument
```
After:
```
$ build/systemd-cgls --unit user@1000
Unit user@1000.service (/user.slice/user-1000.slice/user@1000.service):
├─session.slice (#4939)
│ ├─pipewire-pulse.service (#5203)
│ │ └─7711 /usr/bin/pipewire-pulse
...
```
(Or when -H is used, since -H and -M are incompatible.)
Note that the slightly unusual form with separate boolean variables (hint_vars,
hint_addr) instead of e.g. a const char* variable to hold the message, because this
way we don't trigger the warning about non-literal format.
In general we almost never hit those asserts in production code, so users see
them very rarely, if ever. But either way, we just need something that users
can pass to the developers.
We have quite a few of those asserts, and some have fairly nice messages, but
many are like "WTF?" or "???" or "unexpected something". The error that is
printed includes the file location, and function name. In almost all functions
there's at most one assert, so the function name alone is enough to identify
the failure for a developer. So we don't get much extra from the message, and
we might just as well drop them.
Dropping them makes our code a tiny bit smaller, and most importantly, improves
development experience by making it easy to insert such an assert in the code
without thinking how to phrase the argument.
I think this formatting was originally used because it simplified
adding new options to the help messages. However, these days, most
tools their help message end with "\nSee the %s for details.\n" so
the final line almost never has to be edited which eliminates the
benefit of the custom formatting used for printf() help messages.
Let's make things more consistent and use the same formatting for
printf() help messages that we use everywhere else.
Prompted by https://github.com/systemd/systemd/pull/18355#discussion_r567241580
Presently, CLI utilities such as systemctl will check whether they have a tty
attached or not to decide whether to parse /proc/cmdline or EFI variable
SystemdOptions looking for systemd.log_* entries.
But this check will be misleading if these tools are being launched by a
daemon, such as a monitoring daemon or automation service that runs in
background.
Make log handling of CLI tools uniform by never checking /proc/cmdline or EFI
variables to determine the logging level.
Furthermore, introduce a new log_setup_cli() shortcut to set up common options
used by most command-line utilities.
When emitting the calendarspec warning we want to see some color.
Follow-up for 04220fda5c.
Exceptions:
- systemctl, because it has a lot hand-crafted coloring
- tmpfiles, sysusers, stdio-bridge, etc, because they are also used in
services and I'm not sure if this wouldn't mess up something.
Ideally, coccinelle would strip unnecessary braces too. But I do not see any
option in coccinelle for this, so instead, I edited the patch text using
search&replace to remove the braces. Unfortunately this is not fully automatic,
in particular it didn't deal well with if-else-if-else blocks and ifdefs, so
there is an increased likelikehood be some bugs in such spots.
I also removed part of the patch that coccinelle generated for udev, where we
returns -1 for failure. This should be fixed independently.
Pretty much everything uses just the first argument, and this doesn't make this
common pattern more complicated, but makes it simpler to pass multiple options.
This is a bit like the info link in most of GNU's --help texts, but we
don't do info but man pages, and we make them properly clickable on
terminal supporting that, because awesome.
I think it's generally advisable to link up our (brief) --help texts and
our (more comprehensive) man pages a bit, so this should be an easy and
straight-forward way to do it.
These lines are generally out-of-date, incomplete and unnecessary. With
SPDX and git repository much more accurate and fine grained information
about licensing and authorship is available, hence let's drop the
per-file copyright notice. Of course, removing copyright lines of others
is problematic, hence this commit only removes my own lines and leaves
all others untouched. It might be nicer if sooner or later those could
go away too, making git the only and accurate source of authorship
information.
This part of the copyright blurb stems from the GPL use recommendations:
https://www.gnu.org/licenses/gpl-howto.en.html
The concept appears to originate in times where version control was per
file, instead of per tree, and was a way to glue the files together.
Ultimately, we nowadays don't live in that world anymore, and this
information is entirely useless anyway, as people are very welcome to
copy these files into any projects they like, and they shouldn't have to
change bits that are part of our copyright header for that.
hence, let's just get rid of this old cruft, and shorten our codebase a
bit.
The function is similar to path_kill_slashes() but also removes
initial './', trailing '/.', and '/./' in the path.
When the second argument of path_simplify() is false, then it
behaves as the same as path_kill_slashes(). Hence, this also
replaces path_kill_slashes() with path_simplify().
Files which are installed as-is (any .service and other unit files, .conf
files, .policy files, etc), are left as is. My assumption is that SPDX
identifiers are not yet that well known, so it's better to retain the
extended header to avoid any doubt.
I also kept any copyright lines. We can probably remove them, but it'd nice to
obtain explicit acks from all involved authors before doing that.
Even if pager_open() fails, in general, we should continue the operations.
All erroneous cases in pager_open() show log message in the function.
So, it is not necessary to check the returned value.