mirror of
https://github.com/systemd/systemd.git
synced 2025-01-03 05:18:09 +03:00
Merge pull request #32057 from yuwata/man-example
man: add simple build test for example code
This commit is contained in:
commit
2dcc499bb8
@ -3,7 +3,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sd-event.h>
|
||||
#include <systemd/sd-event.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
pid_t pid = fork();
|
||||
|
@ -2,16 +2,16 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sd-hwdb.h>
|
||||
#include <systemd/sd-hwdb.h>
|
||||
|
||||
int print_usb_properties(uint16_t vid, uint16_t pid) {
|
||||
char match[STRLEN("usb:vp") + DECIMAL_STR_MAX(uint16_t) * 2];
|
||||
char match[128];
|
||||
sd_hwdb *hwdb;
|
||||
const char *key, *value;
|
||||
int r;
|
||||
|
||||
/* Match this USB vendor and product ID combination */
|
||||
xsprintf(match, "usb:v%04Xp%04X", vid, pid);
|
||||
snprintf(match, sizeof match, "usb:v%04Xp%04X", vid, pid);
|
||||
|
||||
r = sd_hwdb_new(&hwdb);
|
||||
if (r < 0)
|
||||
|
@ -11,8 +11,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to open journal: %m\n");
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
SD_JOURNAL_FOREACH_FIELD(j, field)
|
||||
|
@ -7,10 +7,10 @@
|
||||
int main(int argc, char *argv[]) {
|
||||
int r;
|
||||
sd_journal *j;
|
||||
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to open journal: %m\n");
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
SD_JOURNAL_FOREACH(j) {
|
||||
@ -19,8 +19,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
r = sd_journal_get_data(j, "MESSAGE", (const void **)&d, &l);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to read message field: %m\n");
|
||||
fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -12,14 +12,12 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to open journal: %m\n");
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
r = sd_journal_query_unique(j, "_SYSTEMD_UNIT");
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to query journal: %m\n");
|
||||
fprintf(stderr, "Failed to query journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
SD_JOURNAL_FOREACH_UNIQUE(j, d, l)
|
||||
|
@ -7,39 +7,38 @@
|
||||
int main(int argc, char *argv[]) {
|
||||
int r;
|
||||
sd_journal *j;
|
||||
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to open journal: %m\n");
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
const void *d;
|
||||
size_t l;
|
||||
r = sd_journal_next(j);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to iterate to next entry: %m\n");
|
||||
fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
|
||||
break;
|
||||
}
|
||||
if (r == 0) {
|
||||
/* Reached the end, let's wait for changes, and try again */
|
||||
r = sd_journal_wait(j, (uint64_t) -1);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to wait for changes: %m\n");
|
||||
fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
r = sd_journal_get_data(j, "MESSAGE", &d, &l);
|
||||
if (r < 0) {
|
||||
errno = -r;
|
||||
fprintf(stderr, "Failed to read message field: %m\n");
|
||||
fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
|
||||
continue;
|
||||
}
|
||||
printf("%.*s\n", (int) l, (const char*) d);
|
||||
}
|
||||
|
||||
sd_journal_close(j);
|
||||
return 0;
|
||||
}
|
||||
|
@ -10,15 +10,16 @@
|
||||
int main(int argc, char *argv[]) {
|
||||
int fd;
|
||||
FILE *log;
|
||||
|
||||
fd = sd_journal_stream_fd("test", LOG_INFO, 1);
|
||||
if (fd < 0) {
|
||||
errno = -fd;
|
||||
fprintf(stderr, "Failed to create stream fd: %m\n");
|
||||
fprintf(stderr, "Failed to create stream fd: %s\n", strerror(-fd));
|
||||
return 1;
|
||||
}
|
||||
|
||||
log = fdopen(fd, "w");
|
||||
if (!log) {
|
||||
fprintf(stderr, "Failed to create file object: %m\n");
|
||||
fprintf(stderr, "Failed to create file object: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
@ -43,13 +43,10 @@
|
||||
|
||||
#define _cleanup_(f) __attribute__((cleanup(f)))
|
||||
|
||||
#define check(log_level, x) ({ \
|
||||
int _r = (x); \
|
||||
errno = _r < 0 ? -_r : 0; \
|
||||
sd_journal_print((log_level), #x ": %m"); \
|
||||
if (_r < 0) \
|
||||
return EXIT_FAILURE; \
|
||||
})
|
||||
static int log_error(int log_level, int error, const char *str) {
|
||||
sd_journal_print(log_level, "%s failed: %s", str, strerror(-error));
|
||||
return error;
|
||||
}
|
||||
|
||||
typedef enum LogTarget {
|
||||
LOG_TARGET_JOURNAL,
|
||||
@ -193,6 +190,7 @@ int main(int argc, char **argv) {
|
||||
.log_target = LOG_TARGET_JOURNAL,
|
||||
.syslog_identifier = "example",
|
||||
};
|
||||
int r;
|
||||
|
||||
/* https://man7.org/linux/man-pages/man3/setlogmask.3.html
|
||||
* Programs using syslog() instead of sd_journal can use this API to cut logs
|
||||
@ -203,37 +201,49 @@ int main(int argc, char **argv) {
|
||||
/* Acquire a connection to the bus, letting the library work out the details.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_default.html
|
||||
*/
|
||||
check(o.log_level, sd_bus_default(&bus));
|
||||
r = sd_bus_default(&bus);
|
||||
if (r < 0)
|
||||
return log_error(o.log_level, r, "sd_bus_default()");
|
||||
|
||||
/* Publish an interface on the bus, specifying our well-known object access
|
||||
* path and public interface name.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
|
||||
* https://dbus.freedesktop.org/doc/dbus-tutorial.html
|
||||
*/
|
||||
check(o.log_level, sd_bus_add_object_vtable(bus, NULL,
|
||||
"/org/freedesktop/LogControl1",
|
||||
"org.freedesktop.LogControl1",
|
||||
vtable,
|
||||
&o));
|
||||
r = sd_bus_add_object_vtable(bus, NULL,
|
||||
"/org/freedesktop/LogControl1",
|
||||
"org.freedesktop.LogControl1",
|
||||
vtable,
|
||||
&o);
|
||||
if (r < 0)
|
||||
return log_error(o.log_level, r, "sd_bus_add_object_vtable()");
|
||||
|
||||
/* By default the service is assigned an ephemeral name. Also add a fixed
|
||||
* one, so that clients know whom to call.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
|
||||
*/
|
||||
check(o.log_level, sd_bus_request_name(bus, "org.freedesktop.Example", 0));
|
||||
r = sd_bus_request_name(bus, "org.freedesktop.Example", 0);
|
||||
if (r < 0)
|
||||
return log_error(o.log_level, r, "sd_bus_request_name()");
|
||||
|
||||
for (;;) {
|
||||
/* https://www.freedesktop.org/software/systemd/man/sd_bus_wait.html
|
||||
*/
|
||||
check(o.log_level, sd_bus_wait(bus, UINT64_MAX));
|
||||
r = sd_bus_wait(bus, UINT64_MAX);
|
||||
if (r < 0)
|
||||
return log_error(o.log_level, r, "sd_bus_wait()");
|
||||
/* https://www.freedesktop.org/software/systemd/man/sd_bus_process.html
|
||||
*/
|
||||
check(o.log_level, sd_bus_process(bus, NULL));
|
||||
r = sd_bus_process(bus, NULL);
|
||||
if (r < 0)
|
||||
return log_error(o.log_level, r, "sd_bus_process()");
|
||||
}
|
||||
|
||||
/* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html
|
||||
*/
|
||||
check(o.log_level, sd_bus_release_name(bus, "org.freedesktop.Example"));
|
||||
r = sd_bus_release_name(bus, "org.freedesktop.Example");
|
||||
if (r < 0)
|
||||
return log_error(o.log_level, r, "sd_bus_release_name()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -248,3 +248,87 @@ update_man_rules = custom_target(
|
||||
'@0@/man/*.xml'.format(project_source_root),
|
||||
'@0@/rules/meson.build'.format(meson.current_source_dir())],
|
||||
depends : man_page_depends)
|
||||
|
||||
############################################################
|
||||
|
||||
simple_examples = files(
|
||||
'event-quick-child.c',
|
||||
'hwdb-usb-device.c',
|
||||
'id128-app-specific.c',
|
||||
'inotify-watch-tmp.c',
|
||||
'journal-enumerate-fields.c',
|
||||
'journal-iterate-foreach.c',
|
||||
'journal-iterate-poll.c',
|
||||
'journal-iterate-unique.c',
|
||||
'journal-iterate-wait.c',
|
||||
'journal-stream-fd.c',
|
||||
'logcontrol-example.c',
|
||||
'notify-selfcontained-example.c',
|
||||
'path-documents.c',
|
||||
'print-unit-path-call-method.c',
|
||||
'print-unit-path.c',
|
||||
'sd-bus-container-append.c',
|
||||
'sd-bus-container-read.c',
|
||||
'sd_bus_error-example.c',
|
||||
'sd_bus_service_reconnect.c',
|
||||
'send-unit-files-changed.c',
|
||||
'vtable-example.c',
|
||||
)
|
||||
|
||||
examples = []
|
||||
foreach example : simple_examples
|
||||
examples += [ { 'file' : example } ]
|
||||
endforeach
|
||||
|
||||
if conf.get('HAVE_GLIB') == 1
|
||||
examples += [
|
||||
{
|
||||
'file' : files('glib-event-glue.c'),
|
||||
'opts' : [
|
||||
'-I', libglib.get_variable('includedir') / 'glib-2.0',
|
||||
'-I', libglib.get_variable('libdir') / 'glib-2.0/include',
|
||||
],
|
||||
},
|
||||
]
|
||||
endif
|
||||
|
||||
default_args = [
|
||||
cc.cmd_array(),
|
||||
'-c',
|
||||
'-x', 'c',
|
||||
'-pedantic',
|
||||
'-Wall',
|
||||
'-Werror',
|
||||
'-Wextra',
|
||||
'-Wno-unused-parameter',
|
||||
'-o', '/dev/null',
|
||||
'-I', meson.current_source_dir() / '../src',
|
||||
]
|
||||
|
||||
std_args_in = [
|
||||
[ '-std=c99', '-D_GNU_SOURCE', ],
|
||||
[ '-std=c11', '-D_GNU_SOURCE', ],
|
||||
[ '-std=c17', '-D_GNU_SOURCE', ],
|
||||
[ '-std=c23', '-D_GNU_SOURCE', ],
|
||||
[ '-std=gnu99', ],
|
||||
[ '-std=gnu11', ],
|
||||
[ '-std=gnu17', ],
|
||||
[ '-std=gnu23', ],
|
||||
]
|
||||
|
||||
std_args = []
|
||||
foreach std : std_args_in
|
||||
if cc.has_argument(std[0])
|
||||
std_args += [std]
|
||||
endif
|
||||
endforeach
|
||||
|
||||
foreach item : examples
|
||||
foreach std : std_args
|
||||
file = item.get('file')
|
||||
test('cc-' + fs.stem(file) + '-' + std[0].split('=')[1],
|
||||
env,
|
||||
suite : 'example',
|
||||
args : default_args + std + item.get('opts', []) + [file])
|
||||
endforeach
|
||||
endforeach
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sd-path.h>
|
||||
#include <systemd/sd-path.h>
|
||||
|
||||
int main(void) {
|
||||
int r;
|
||||
|
@ -21,8 +21,7 @@
|
||||
#define MEMBER "GetUnitByPID"
|
||||
|
||||
static int log_error(int error, const char *message) {
|
||||
errno = -error;
|
||||
fprintf(stderr, "%s: %m\n", message);
|
||||
fprintf(stderr, "%s: %s\n", message, strerror(-error));
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,7 @@
|
||||
#define MEMBER "GetUnitByPID"
|
||||
|
||||
static int log_error(int error, const char *message) {
|
||||
errno = -error;
|
||||
fprintf(stderr, "%s: %m\n", message);
|
||||
fprintf(stderr, "%s: %s\n", message, strerror(-error));
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sd-bus.h>
|
||||
#include <systemd/sd-bus.h>
|
||||
|
||||
int writer_with_negative_errno_return(int fd, sd_bus_error *error) {
|
||||
const char *message = "Hello, World!\n";
|
||||
@ -14,5 +14,5 @@ int writer_with_negative_errno_return(int fd, sd_bus_error *error) {
|
||||
|
||||
/* On error, initialize the error structure, and also propagate the errno
|
||||
* value that write(2) set for us. */
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to write to fd %i: %m", fd);
|
||||
return sd_bus_error_set_errnof(error, errno, "Failed to write to fd %i: %s", fd, strerror(errno));
|
||||
}
|
||||
|
@ -42,13 +42,10 @@
|
||||
|
||||
#define _cleanup_(f) __attribute__((cleanup(f)))
|
||||
|
||||
#define check(x) ({ \
|
||||
int _r = (x); \
|
||||
errno = _r < 0 ? -_r : 0; \
|
||||
printf(#x ": %m\n"); \
|
||||
if (_r < 0) \
|
||||
return EXIT_FAILURE; \
|
||||
})
|
||||
static int log_error(int r, const char *str) {
|
||||
fprintf(stderr, "%s failed: %s\n", str, strerror(-r));
|
||||
return r;
|
||||
}
|
||||
|
||||
typedef struct object {
|
||||
const char *example;
|
||||
@ -90,13 +87,24 @@ static const sd_bus_vtable vtable[] = {
|
||||
static int setup(object *o);
|
||||
|
||||
static int on_disconnect(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
|
||||
check(setup((object *)userdata));
|
||||
return 0;
|
||||
int r;
|
||||
|
||||
r = setup((object *)userdata);
|
||||
if (r < 0) {
|
||||
object *o = userdata;
|
||||
r = sd_event_exit(*o->event, r);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_event_exit()");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Ensure the event loop exits with a clear error if acquiring the well-known
|
||||
* service name fails */
|
||||
static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
int r;
|
||||
|
||||
if (!sd_bus_message_is_method_error(m, NULL))
|
||||
return 1;
|
||||
|
||||
@ -105,21 +113,27 @@ static int request_name_callback(sd_bus_message *m, void *userdata, sd_bus_error
|
||||
if (sd_bus_error_has_names(error, SD_BUS_ERROR_TIMEOUT, SD_BUS_ERROR_NO_REPLY))
|
||||
return 1; /* The bus is not available, try again later */
|
||||
|
||||
printf("Failed to request name: %s\n", error->message);
|
||||
fprintf(stderr, "Failed to request name: %s\n", error->message);
|
||||
object *o = userdata;
|
||||
check(sd_event_exit(*o->event, -sd_bus_error_get_errno(error)));
|
||||
r = sd_event_exit(*o->event, -sd_bus_error_get_errno(error));
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_event_exit()");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setup(object *o) {
|
||||
int r;
|
||||
|
||||
/* If we are reconnecting, then the bus object needs to be closed, detached
|
||||
* from the event loop and recreated.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_detach_event.html
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_close_unref.html
|
||||
*/
|
||||
if (*o->bus) {
|
||||
check(sd_bus_detach_event(*o->bus));
|
||||
r = sd_bus_detach_event(*o->bus);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_detach_event()");
|
||||
*o->bus = sd_bus_close_unref(*o->bus);
|
||||
}
|
||||
|
||||
@ -135,55 +149,75 @@ static int setup(object *o) {
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_set_connected_signal.html
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_start.html
|
||||
*/
|
||||
check(sd_bus_new(o->bus));
|
||||
check(sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket"));
|
||||
check(sd_bus_set_bus_client(*o->bus, 1));
|
||||
check(sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS));
|
||||
check(sd_bus_set_watch_bind(*o->bus, 1));
|
||||
check(sd_bus_start(*o->bus));
|
||||
r = sd_bus_new(o->bus);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_new()");
|
||||
r = sd_bus_set_address(*o->bus, "unix:path=/run/dbus/system_bus_socket");
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_set_address()");
|
||||
r = sd_bus_set_bus_client(*o->bus, 1);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_set_bus_client()");
|
||||
r = sd_bus_negotiate_creds(*o->bus, 1, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_negotiate_creds()");
|
||||
r = sd_bus_set_watch_bind(*o->bus, 1);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_set_watch_bind()");
|
||||
r = sd_bus_start(*o->bus);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_start()");
|
||||
|
||||
/* Publish an interface on the bus, specifying our well-known object access
|
||||
* path and public interface name.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_add_object.html
|
||||
* https://dbus.freedesktop.org/doc/dbus-tutorial.html
|
||||
*/
|
||||
check(sd_bus_add_object_vtable(*o->bus,
|
||||
NULL,
|
||||
"/org/freedesktop/ReconnectExample",
|
||||
"org.freedesktop.ReconnectExample",
|
||||
vtable,
|
||||
o));
|
||||
r = sd_bus_add_object_vtable(*o->bus,
|
||||
NULL,
|
||||
"/org/freedesktop/ReconnectExample",
|
||||
"org.freedesktop.ReconnectExample",
|
||||
vtable,
|
||||
o);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_add_object_vtable()");
|
||||
/* By default the service is only assigned an ephemeral name. Also add a
|
||||
* well-known one, so that clients know whom to call. This needs to be
|
||||
* asynchronous, as D-Bus might not be yet available. The callback will check
|
||||
* whether the error is expected or not, in case it fails.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_request_name.html
|
||||
*/
|
||||
check(sd_bus_request_name_async(*o->bus,
|
||||
NULL,
|
||||
"org.freedesktop.ReconnectExample",
|
||||
0,
|
||||
request_name_callback,
|
||||
o));
|
||||
r = sd_bus_request_name_async(*o->bus,
|
||||
NULL,
|
||||
"org.freedesktop.ReconnectExample",
|
||||
0,
|
||||
request_name_callback,
|
||||
o);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_request_name_async()");
|
||||
/* When D-Bus is disconnected this callback will be invoked, which will set up
|
||||
* the connection again. This needs to be asynchronous, as D-Bus might not yet
|
||||
* be available.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_match_signal_async.html
|
||||
*/
|
||||
check(sd_bus_match_signal_async(*o->bus,
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Local",
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Local",
|
||||
"Disconnected",
|
||||
on_disconnect,
|
||||
NULL,
|
||||
o));
|
||||
r = sd_bus_match_signal_async(*o->bus,
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Local",
|
||||
NULL,
|
||||
"org.freedesktop.DBus.Local",
|
||||
"Disconnected",
|
||||
on_disconnect,
|
||||
NULL,
|
||||
o);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_match_signal_async()");
|
||||
/* Attach the bus object to the event loop so that calls and signals are
|
||||
* processed.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_bus_attach_event.html
|
||||
*/
|
||||
check(sd_bus_attach_event(*o->bus, *o->event, 0));
|
||||
r = sd_bus_attach_event(*o->bus, *o->event, 0);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_attach_event()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -199,28 +233,42 @@ int main(int argc, char **argv) {
|
||||
.bus = &bus,
|
||||
.event = &event,
|
||||
};
|
||||
int r;
|
||||
|
||||
/* Create an event loop data structure, with default parameters.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_event_default.html
|
||||
*/
|
||||
check(sd_event_default(&event));
|
||||
r = sd_event_default(&event);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_event_default()");
|
||||
|
||||
/* By default the event loop will terminate when all sources have disappeared,
|
||||
* so we have to keep it 'occupied'. Register signal handling to do so.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_event_add_signal.html
|
||||
*/
|
||||
check(sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL));
|
||||
check(sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL));
|
||||
r = sd_event_add_signal(event, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_event_add_signal(SIGINT)");
|
||||
|
||||
check(setup(&o));
|
||||
r = sd_event_add_signal(event, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_event_add_signal(SIGTERM)");
|
||||
|
||||
r = setup(&o);
|
||||
if (r < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
/* Enter the main loop, it will exit only on sigint/sigterm.
|
||||
* https://www.freedesktop.org/software/systemd/man/sd_event_loop.html
|
||||
*/
|
||||
check(sd_event_loop(event));
|
||||
r = sd_event_loop(event);
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_event_loop()");
|
||||
|
||||
/* https://www.freedesktop.org/software/systemd/man/sd_bus_release_name.html */
|
||||
check(sd_bus_release_name(bus, "org.freedesktop.ReconnectExample"));
|
||||
r = sd_bus_release_name(bus, "org.freedesktop.ReconnectExample");
|
||||
if (r < 0)
|
||||
return log_error(r, "sd_bus_release_name()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,20 +9,14 @@
|
||||
|
||||
#define _cleanup_(f) __attribute__((cleanup(f)))
|
||||
|
||||
#define check(x) ({ \
|
||||
int r = (x); \
|
||||
errno = r < 0 ? -r : 0; \
|
||||
printf(#x ": %m\n"); \
|
||||
if (r < 0) \
|
||||
return EXIT_FAILURE; \
|
||||
})
|
||||
|
||||
typedef struct object {
|
||||
char *name;
|
||||
uint32_t number;
|
||||
} object;
|
||||
|
||||
static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
int r;
|
||||
|
||||
printf("Got called with userdata=%p\n", userdata);
|
||||
|
||||
if (sd_bus_message_is_method_call(m,
|
||||
@ -31,8 +25,17 @@ static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
|
||||
return 1;
|
||||
|
||||
const char *string;
|
||||
check(sd_bus_message_read(m, "s", &string));
|
||||
check(sd_bus_reply_method_return(m, "s", string));
|
||||
r = sd_bus_message_read(m, "s", &string);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_message_read() failed: %s\n", strerror(-r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_reply_method_return(m, "s", string);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_reply_method_return() failed: %s\n", strerror(-r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -84,28 +87,55 @@ static const sd_bus_vtable vtable[] = {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
sd_bus_default(&bus);
|
||||
|
||||
object object = { .number = 666 };
|
||||
check((object.name = strdup("name")) != NULL);
|
||||
|
||||
check(sd_bus_add_object_vtable(bus, NULL,
|
||||
"/org/freedesktop/systemd/VtableExample",
|
||||
"org.freedesktop.systemd.VtableExample",
|
||||
vtable,
|
||||
&object));
|
||||
|
||||
check(sd_bus_request_name(bus,
|
||||
"org.freedesktop.systemd.VtableExample",
|
||||
0));
|
||||
|
||||
for (;;) {
|
||||
check(sd_bus_wait(bus, UINT64_MAX));
|
||||
check(sd_bus_process(bus, NULL));
|
||||
object.name = strdup("name");
|
||||
if (!object.name) {
|
||||
fprintf(stderr, "OOM\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
r = sd_bus_add_object_vtable(bus, NULL,
|
||||
"/org/freedesktop/systemd/VtableExample",
|
||||
"org.freedesktop.systemd.VtableExample",
|
||||
vtable,
|
||||
&object);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_add_object_vtable() failed: %s\n", strerror(-r));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
r = sd_bus_request_name(bus,
|
||||
"org.freedesktop.systemd.VtableExample",
|
||||
0);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_request_name() failed: %s\n", strerror(-r));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
r = sd_bus_wait(bus, UINT64_MAX);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_wait() failed: %s\n", strerror(-r));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
r = sd_bus_process(bus, NULL);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_process() failed: %s\n", strerror(-r));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_release_name(bus, "org.freedesktop.systemd.VtableExample");
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "sd_bus_release_name() failed: %s\n", strerror(-r));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
check(sd_bus_release_name(bus, "org.freedesktop.systemd.VtableExample"));
|
||||
free(object.name);
|
||||
|
||||
return 0;
|
||||
|
@ -208,6 +208,7 @@ struct sd_bus_vtable {
|
||||
_41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \
|
||||
NAME, ...) NAME
|
||||
|
||||
#define _SD_VARARGS_FOREACH_EVEN_00(FN)
|
||||
#define _SD_VARARGS_FOREACH_EVEN_01(FN, X) FN(X)
|
||||
#define _SD_VARARGS_FOREACH_EVEN_02(FN, X, Y) FN(X)
|
||||
#define _SD_VARARGS_FOREACH_EVEN_04(FN, X, Y, ...) FN(X) _SD_VARARGS_FOREACH_EVEN_02(FN, __VA_ARGS__)
|
||||
@ -261,9 +262,11 @@ struct sd_bus_vtable {
|
||||
_SD_VARARGS_FOREACH_EVEN_08, _SD_VARARGS_FOREACH_EVEN_07, \
|
||||
_SD_VARARGS_FOREACH_EVEN_06, _SD_VARARGS_FOREACH_EVEN_05, \
|
||||
_SD_VARARGS_FOREACH_EVEN_04, _SD_VARARGS_FOREACH_EVEN_03, \
|
||||
_SD_VARARGS_FOREACH_EVEN_02, _SD_VARARGS_FOREACH_EVEN_01) \
|
||||
_SD_VARARGS_FOREACH_EVEN_02, _SD_VARARGS_FOREACH_EVEN_01, \
|
||||
_SD_VARARGS_FOREACH_EVEN_00) \
|
||||
(FN, __VA_ARGS__)
|
||||
|
||||
#define _SD_VARARGS_FOREACH_ODD_00(FN)
|
||||
#define _SD_VARARGS_FOREACH_ODD_01(FN, X)
|
||||
#define _SD_VARARGS_FOREACH_ODD_02(FN, X, Y) FN(Y)
|
||||
#define _SD_VARARGS_FOREACH_ODD_04(FN, X, Y, ...) FN(Y) _SD_VARARGS_FOREACH_ODD_02(FN, __VA_ARGS__)
|
||||
@ -317,7 +320,8 @@ struct sd_bus_vtable {
|
||||
_SD_VARARGS_FOREACH_ODD_08, _SD_VARARGS_FOREACH_ODD_07, \
|
||||
_SD_VARARGS_FOREACH_ODD_06, _SD_VARARGS_FOREACH_ODD_05, \
|
||||
_SD_VARARGS_FOREACH_ODD_04, _SD_VARARGS_FOREACH_ODD_03, \
|
||||
_SD_VARARGS_FOREACH_ODD_02, _SD_VARARGS_FOREACH_ODD_01) \
|
||||
_SD_VARARGS_FOREACH_ODD_02, _SD_VARARGS_FOREACH_ODD_01, \
|
||||
_SD_VARARGS_FOREACH_ODD_00) \
|
||||
(FN, __VA_ARGS__)
|
||||
|
||||
#define SD_BUS_ARGS(...) __VA_ARGS__
|
||||
|
Loading…
Reference in New Issue
Block a user