initctl: the status views over D-Bus

The summary table, the per-service detail, JSON and the quiet and
ident forms all read state Finit already publishes, so they read it
from the bus like everything else rather than through a second path
that has to be kept in step.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2026-08-13 09:28:26 +02:00
1 parent ebc0ef62e6
commit 6310d9e760
16 files changed
+1271 -315

No files matched your search

+2
View File
@@ -333,6 +333,7 @@ static int handle_properties_get(link_connection_t *conn, const struct link_msg
if (!p->getter)
break;
__w_init(&w, conn->txbuf, sizeof(conn->txbuf));
__w_sig(&w, p->sig ? p->sig : "s");
if (p->getter(&w, e->userdata) != 0 || (blen = __w_finish(&w)) < 0)
return __send_error(conn, m,
"org.freedesktop.DBus.Error.Failed",
@@ -380,6 +381,7 @@ static int handle_properties_get_all(link_connection_t *conn, const struct link_
continue;
__w_struct_begin(&w);
__w_string(&w, p->name);
__w_sig(&w, p->sig ? p->sig : "s");
if (p->getter(&w, e->userdata) != 0)
return __send_error(conn, m,
"org.freedesktop.DBus.Error.Failed",
+2
View File
@@ -312,6 +312,8 @@ int link_r_bool (link_reader_t *r, int *o) { return __r_bool (r, o);
int link_r_u32 (link_reader_t *r, uint32_t *o) { return __r_u32 (r, o); }
int link_r_string(link_reader_t *r, const char **o) { return __r_string(r, o); }
int link_r_path (link_reader_t *r, const char **o) { return __r_path (r, o); }
int link_r_variant_begin (link_reader_t *r, char *type) { return __r_variant_begin(r, type); }
int link_r_skip_basic (link_reader_t *r, char type) { return __r_skip_basic(r, type); }
int link_r_variant_string(link_reader_t *r, const char **o) { return __r_variant_string(r, o); }
int link_r_align (link_reader_t *r, size_t n) { return __r_align (r, n); }
int link_r_array_begin(link_reader_t *r, size_t *e) { return __r_array_begin(r, e); }
+7 -3
View File
@@ -129,9 +129,11 @@ typedef struct {
} link_method_t;
/* A read-only property descriptor. Set via the Properties.Set side
* is not yet implemented; only Get and GetAll are. The getter writes
* the property's value as a D-Bus variant (use link_w_variant_string
* for "s"-typed properties) into the provided writer. */
* is not yet implemented; only Get and GetAll are. The framework
* emits the variant signature from `sig`; the getter writes only the
* bare value into the provided writer (link_w_string for "s",
* link_w_u32 for "u", ...), so the declared type is the single
* source of truth. */
typedef int (*link_property_getter_fn)(link_writer_t *w, void *userdata);
typedef struct {
@@ -329,6 +331,8 @@ int link_r_bool (link_reader_t *r, int *out);
int link_r_u32 (link_reader_t *r, uint32_t *out);
int link_r_string (link_reader_t *r, const char **out); /* "s" */
int link_r_path (link_reader_t *r, const char **out); /* "o" */
int link_r_variant_begin (link_reader_t *r, char *type); /* sig header, cursor at value */
int link_r_skip_basic (link_reader_t *r, char type); /* skip one basic value */
int link_r_variant_string(link_reader_t *r, const char **out); /* "v" containing "s" */
int link_r_align (link_reader_t *r, size_t n); /* skip to next n-byte boundary */
int link_r_done (const link_reader_t *r);
+73 -16
View File
@@ -110,6 +110,7 @@ void __w_variant_string(struct link_writer *w, const char *s)
__w_string(w, s);
}
static size_t element_align(char c)
{
switch (c) {
@@ -262,32 +263,88 @@ static int read_string_like(struct link_reader *r, const char **out)
int __r_string(struct link_reader *r, const char **out) { return read_string_like(r, out); }
int __r_path (struct link_reader *r, const char **out) { return read_string_like(r, out); }
/*
* Parse a variant's signature header, i.e. "g" wire form: 1-byte
* length, bytes, NUL. Only single-character inner signatures are
* supported. On success the cursor sits at the value and the type
* code is returned in *type.
*/
int __r_variant_begin(struct link_reader *r, char *type)
{
uint8_t sig_len;
if (r_skip_align(r, 1) < 0 || r->off + 1 > r->cap)
goto fail;
sig_len = r->base[r->off++];
if (sig_len != 1 || r->off + 2 > r->cap)
goto fail;
if (r->base[r->off + 1] != 0)
goto fail;
*type = (char)r->base[r->off];
r->off += 2;
return 0;
fail:
r->err = 1;
return -1;
}
/* Read a variant "v" expected to contain a string. Fails if the
* inner signature is anything other than "s" (returns -1, *out set
* to NULL). */
int __r_variant_string(struct link_reader *r, const char **out)
{
uint8_t sig_len;
uint32_t slen;
char type;
*out = NULL;
/* signature is "g" wire form: 1-byte length, bytes, NUL */
if (r_skip_align(r, 1) < 0 || r->off + 1 > r->cap) { r->err = 1; return -1; }
sig_len = r->base[r->off++];
if (sig_len != 1 || r->off + 2 > r->cap) { r->err = 1; return -1; }
if (r->base[r->off] != 's' || r->base[r->off + 1] != 0) { r->err = 1; return -1; }
r->off += 2;
/* now a normal string */
if (__r_u32(r, &slen) < 0) return -1;
if (r->off + (size_t)slen + 1 > r->cap || r->base[r->off + slen] != 0) {
if (__r_variant_begin(r, &type) < 0)
return -1;
if (type != 's') {
r->err = 1;
return -1;
}
*out = (const char *)(r->base + r->off);
r->off += (size_t)slen + 1;
return 0;
return read_string_like(r, out);
}
/*
* Skip one basic value of the given type code, as returned by
* __r_variant_begin(). Lets a{sv} consumers tolerate value types
* they don't know. Returns -1 on non-basic types.
*/
int __r_skip_basic(struct link_reader *r, char type)
{
const char *s;
uint32_t u;
uint8_t y;
switch (type) {
case 's':
case 'o':
return read_string_like(r, &s);
case 'b':
case 'u':
case 'i':
return __r_u32(r, &u);
case 'y':
return __r_byte(r, &y);
default:
r->err = 1;
return -1;
}
}
/* Read a variant "v" expected to contain a uint32. */
int __r_variant_u32(struct link_reader *r, uint32_t *out)
{
char type;
if (__r_variant_begin(r, &type) < 0)
return -1;
if (type != 'u') {
r->err = 1;
return -1;
}
return __r_u32(r, out);
}
int __r_done(const struct link_reader *r)
+3
View File
@@ -44,7 +44,10 @@ int __r_bool (struct link_reader *r, int *out);
int __r_u32 (struct link_reader *r, uint32_t *out);
int __r_string(struct link_reader *r, const char **out); /* "s" */
int __r_path (struct link_reader *r, const char **out); /* "o" */
int __r_variant_begin (struct link_reader *r, char *type); /* sig header, cursor at value */
int __r_skip_basic (struct link_reader *r, char type); /* skip one basic value */
int __r_variant_string(struct link_reader *r, const char **out); /* "v" containing "s" */
int __r_variant_u32 (struct link_reader *r, uint32_t *out); /* "v" containing "u" */
int __r_align (struct link_reader *r, size_t n); /* skip to n-byte boundary */
int __r_array_begin(struct link_reader *r, size_t *out_end);
int __r_done (const struct link_reader *r);