timedatectl.c revision 2f6a59070559786428d9eaf199ae3d61772b2225
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/***
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2012 Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2013 Kay Sievers
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is free software; you can redistribute it and/or modify it
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen under the terms of the GNU Lesser General Public License as published by
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen (at your option) any later version.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen systemd is distributed in the hope that it will be useful, but
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Lesser General Public License for more details.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen You should have received a copy of the GNU Lesser General Public License
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen***/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <stdlib.h>
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen#include <stdbool.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <unistd.h>
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen#include <getopt.h>
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen#include <locale.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <string.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <sys/timex.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "sd-bus.h"
d122f9ee3a0e3c02ff8100a3dcd1866e90a6537aTom Gundersen#include "bus-util.h"
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen#include "bus-error.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "util.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "spawn-polkit-agent.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "build.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "strv.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "pager.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "time-dst.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic bool arg_adjust_system_clock = false;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic bool arg_no_pager = false;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic bool arg_ask_password = true;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic char *arg_host = NULL;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic void pager_open_if_enabled(void) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (arg_no_pager)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen pager_open(false);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersenstatic void polkit_agent_open_if_enabled(void) {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen /* Open the polkit agent as a child process if necessary */
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen if (!arg_ask_password)
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen return;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen polkit_agent_open();
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen}
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersentypedef struct StatusInfo {
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen usec_t time;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen const char *timezone;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen usec_t rtc_time;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen bool rtc_local;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen bool ntp_enabled;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen bool ntp_capable;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen bool ntp_synced;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen} StatusInfo;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic const char *jump_str(int delta_minutes, char *s, size_t size) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (delta_minutes == 60)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return "one hour forward";
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (delta_minutes == -60)
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return "one hour backwards";
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (delta_minutes < 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen snprintf(s, size, "%i minutes backwards", -delta_minutes);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return s;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (delta_minutes > 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen snprintf(s, size, "%i minutes forward", delta_minutes);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return s;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return "";
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic void print_status_info(StatusInfo *i) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char a[FORMAT_TIMESTAMP_MAX];
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char b[FORMAT_TIMESTAMP_MAX];
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char s[32];
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen struct tm tm;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen time_t sec;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char *zc, *zn;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen time_t t, tc, tn;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int dn;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen bool is_dstc, is_dstn;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(i);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen /* Enforce the values of /etc/localtime */
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (getenv("TZ")) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen fprintf(stderr, "Warning: ignoring the TZ variable, reading the system's timezone setting only.\n\n");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen unsetenv("TZ");
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen sec = (time_t) (i->time / USEC_PER_SEC);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char_array_0(a);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering printf(" Local time: %s\n", a);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering char_array_0(a);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen printf(" Universal time: %s\n", a);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (i->rtc_time > 0) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering time_t rtc_sec;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering zero(tm);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", gmtime_r(&rtc_sec, &tm)) > 0);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering char_array_0(a);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering printf(" RTC time: %s\n", a);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering } else
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering printf(" RTC time: n/a\n");
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(strftime(a, sizeof(a), "%Z, %z", localtime_r(&sec, &tm)) > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen char_array_0(a);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen printf(" Timezone: %s (%s)\n"
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen " NTP enabled: %s\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "NTP synchronized: %s\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " RTC in local TZ: %s\n",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen strna(i->timezone), a,
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen yes_no(i->ntp_synced),
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen yes_no(i->rtc_local));
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = time_get_dst(sec, "/etc/localtime",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen &tc, &zc, &is_dstc,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen &tn, &dn, &zn, &is_dstn);
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen if (r < 0)
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen printf(" DST active: n/a\n");
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen else {
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen printf(" DST active: %s\n", yes_no(is_dstc));
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen t = tc - 1;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen char_array_0(a);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)) > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen char_array_0(b);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen printf(" Last DST change: DST %s at\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " %s\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " %s\n",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen is_dstc ? "began" : "ended", a, b);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen t = tn - 1;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(strftime(a, sizeof(a), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)) > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen char_array_0(a);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(tm);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert_se(strftime(b, sizeof(b), "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)) > 0);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen char_array_0(b);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen printf(" Next DST change: DST %s (the clock jumps %s) at\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " %s\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " %s\n",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen is_dstn ? "begins" : "ends", jump_str(dn, s, sizeof(s)), a, b);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen free(zc);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen free(zn);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (i->rtc_local)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen fputs("\n" ANSI_HIGHLIGHT_ON
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "Warning: The RTC is configured to maintain time in the local timezone. This\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " mode is not fully supported and will create various problems with time\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " zone changes and daylight saving adjustments. If at all possible use\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " RTC in UTC, by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen}
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersenstatic int get_timedate_property_bool(sd_bus *bus, const char *name, bool *target) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen int r;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen assert(name);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = sd_bus_get_property(bus,
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen "org.freedesktop.timedate1",
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen "/org/freedesktop/timedate1",
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen "org.freedesktop.timedate1",
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen name,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen &error,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen &reply,
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen "b");
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to get property: %s %s", name, bus_error_message(&error, -r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_read(reply, "b", target);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse reply.");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int get_timedate_property_usec(sd_bus *bus, const char *name, usec_t *target) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(name);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_get_property(bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen name,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &error,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &reply,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "t");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to get property: %s %s", name, bus_error_message(&error, -r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_read(reply, "t", target);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse reply.");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int show_status(sd_bus *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen StatusInfo info = {};
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(bus);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_get_property(bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "Timezone",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &error,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &reply,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "s");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to get property: Timezone %s", bus_error_message(&error, -r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_message_read(reply, "s", &info.timezone);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = get_timedate_property_bool(bus, "LocalRTC", &info.rtc_local);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = get_timedate_property_bool(bus, "NTP", &info.ntp_enabled);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = get_timedate_property_bool(bus, "CanNTP", &info.ntp_capable);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = get_timedate_property_bool(bus, "NTPSynchronized", &info.ntp_synced);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = get_timedate_property_usec(bus, "TimeUSec", &info.time);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = get_timedate_property_usec(bus, "RTCTimeUSec", &info.rtc_time);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen print_status_info(&info);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_time(sd_bus *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bool relative = false, interactive = arg_ask_password;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen usec_t t;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(args);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(n == 2);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen polkit_agent_open_if_enabled();
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = parse_timestamp(args[1], &t);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse time specification: %s", args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_call_method(bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetTime",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &error,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen NULL,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "xbb", (int64_t)t, relative, interactive);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0)
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to set time: %s", bus_error_message(&error, -r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_timezone(sd_bus *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bool interactive = arg_ask_password;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(args);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(n == 2);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen polkit_agent_open_if_enabled();
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen r = sd_bus_call_method(bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen "SetTimezone",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &error,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen NULL,
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen "sb", args[1], interactive);
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen if (r < 0)
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen log_error("Failed to set timezone: %s", bus_error_message(&error, -r));
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_local_rtc(sd_bus *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bool interactive = arg_ask_password, b, q;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen int r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(args);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(n == 2);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen polkit_agent_open_if_enabled();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = parse_boolean(args[1]);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r < 0) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_error("Failed to parse local RTC setting: %s", args[1]);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen b = r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen q = arg_adjust_system_clock;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = sd_bus_call_method(bus,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "org.freedesktop.timedate1",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "/org/freedesktop/timedate1",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "org.freedesktop.timedate1",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "SetLocalRTC",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen &error,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen NULL,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "bbb", b, q, interactive);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (r < 0)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_error("Failed to set local RTC: %s", bus_error_message(&error, -r));
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen}
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int set_ntp(sd_bus *bus, char **args, unsigned n) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen bool interactive = arg_ask_password, b;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen int r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(args);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen assert(n == 2);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen polkit_agent_open_if_enabled();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = parse_boolean(args[1]);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_error("Failed to parse NTP setting: %s", args[1]);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen return r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen b = r;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen r = sd_bus_call_method(bus,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "org.freedesktop.timedate1",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "/org/freedesktop/timedate1",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "org.freedesktop.timedate1",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "SetNTP",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen &error,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen NULL,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen "bb", b, interactive);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Failed to set ntp: %s", bus_error_message(&error, -r));
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return r;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic int list_timezones(sd_bus *bus, char **args, unsigned n) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen _cleanup_fclose_ FILE *f = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen _cleanup_strv_free_ char **zones = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen size_t n_zones = 0;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen assert(args);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen assert(n == 1);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen f = fopen("/usr/share/zoneinfo/zone.tab", "re");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (!f) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Failed to open timezone database: %m");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return -errno;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen for (;;) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen char l[LINE_MAX], *p, **z, *w;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen size_t k;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (!fgets(l, sizeof(l), f)) {
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (feof(f))
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen break;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_error("Failed to read timezone database: %m");
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen return -errno;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen p = strstrip(l);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen if (isempty(p) || *p == '#')
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen continue;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen /* Skip over country code */
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen p += strcspn(p, WHITESPACE);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen p += strspn(p, WHITESPACE);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen /* Skip over coordinates */
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen p += strcspn(p, WHITESPACE);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen p += strspn(p, WHITESPACE);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen /* Found timezone name */
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen k = strcspn(p, WHITESPACE);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen if (k <= 0)
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen continue;
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen w = strndup(p, k);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen if (!w)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return log_oom();
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen z = realloc(zones, sizeof(char*) * (n_zones + 2));
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (!z) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen free(w);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return log_oom();
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen zones = z;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen zones[n_zones++] = w;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (zones)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen zones[n_zones] = NULL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen pager_open_if_enabled();
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen strv_sort(zones);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen strv_print(zones);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen}
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersenstatic int help(void) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen printf("%s [OPTIONS...] COMMAND ...\n\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen "Query or change system time and date settings.\n\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " -h --help Show this help\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " --version Show package version\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " --adjust-system-clock\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " Adjust system clock when changing local RTC mode\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " --no-pager Do not pipe output into a pager\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " --no-ask-password Do not prompt for password\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " -H --host=[USER@]HOST Operate on remote host\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " -M --machine=CONTAINER Operate on local container\n\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen "Commands:\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " status Show current time settings\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " set-time TIME Set system time\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " set-timezone ZONE Set system timezone\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " list-timezones Show known timezones\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " set-local-rtc BOOL Control whether RTC is in local time\n"
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen " set-ntp BOOL Control whether NTP is enabled\n",
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen program_invocation_short_name);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen}
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersenstatic int parse_argv(int argc, char *argv[]) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen enum {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen ARG_VERSION = 0x100,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen ARG_NO_PAGER,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen ARG_ADJUST_SYSTEM_CLOCK,
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen ARG_NO_ASK_PASSWORD
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen };
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen static const struct option options[] = {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "help", no_argument, NULL, 'h' },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "version", no_argument, NULL, ARG_VERSION },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "no-pager", no_argument, NULL, ARG_NO_PAGER },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "host", required_argument, NULL, 'H' },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "machine", required_argument, NULL, 'M' },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen { NULL, 0, NULL, 0 }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen };
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen int c;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen assert(argc >= 0);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen assert(argv);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen while ((c = getopt_long(argc, argv, "hH:M:", options, NULL)) >= 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen switch (c) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen case 'h':
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen help();
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen case ARG_VERSION:
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen puts(PACKAGE_STRING);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen puts(SYSTEMD_FEATURES);
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen return 0;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen case 'H':
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen arg_transport = BUS_TRANSPORT_REMOTE;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen arg_host = optarg;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen break;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen case 'M':
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen arg_transport = BUS_TRANSPORT_CONTAINER;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen arg_host = optarg;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen break;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen case ARG_NO_ASK_PASSWORD:
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen arg_ask_password = false;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen break;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen case ARG_ADJUST_SYSTEM_CLOCK:
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen arg_adjust_system_clock = true;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen break;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen case ARG_NO_PAGER:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen arg_no_pager = true;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen break;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen case '?':
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen return -EINVAL;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen default:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error("Unknown option code %c", c);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return -EINVAL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return 1;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int timedatectl_main(sd_bus *bus, int argc, char *argv[]) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen static const struct {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen const char* verb;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen const enum {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen MORE,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen LESS,
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen EQUAL
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen } argc_cmp;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen const int argc;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen } verbs[] = {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen { "status", LESS, 1, show_status },
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen { "set-time", EQUAL, 2, set_time },
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen { "set-timezone", EQUAL, 2, set_timezone },
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen { "list-timezones", EQUAL, 1, list_timezones },
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen { "set-local-rtc", EQUAL, 2, set_local_rtc },
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen { "set-ntp", EQUAL, 2, set_ntp, },
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen };
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int left;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen unsigned i;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(argc >= 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(argv);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen left = argc - optind;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (left <= 0)
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen /* Special rule: no arguments means "status" */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen i = 0;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen else {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (streq(argv[optind], "help")) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen help();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return 0;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen for (i = 0; i < ELEMENTSOF(verbs); i++)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (streq(argv[optind], verbs[i].verb))
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen break;
be077570f779664ed87b50f60608df9fbe258821Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (i >= ELEMENTSOF(verbs)) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen log_error("Unknown operation %s", argv[optind]);
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen return -EINVAL;
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen }
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen }
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen switch (verbs[i].argc_cmp) {
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen case EQUAL:
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen if (left != verbs[i].argc) {
5b34277c2015e32e51d10cfa076df2c7106b4537Tom Gundersen log_error("Invalid number of arguments.");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return -EINVAL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen break;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen case MORE:
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (left < verbs[i].argc) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Too few arguments.");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return -EINVAL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen break;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen case LESS:
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (left > verbs[i].argc) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Too many arguments.");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return -EINVAL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen break;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen default:
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen assert_not_reached("Unknown comparison operator.");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return verbs[i].dispatch(bus, argv + optind, left);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenint main(int argc, char *argv[]) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen int r, ret = EXIT_FAILURE;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen _cleanup_bus_unref_ sd_bus *bus = NULL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen setlocale(LC_ALL, "");
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_parse_environment();
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_open();
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen r = parse_argv(argc, argv);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0)
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen goto finish;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen else if (r == 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen ret = EXIT_SUCCESS;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen goto finish;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen r = bus_open_transport(arg_transport, arg_host, false, &bus);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen if (r < 0) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Failed to create bus connection: %s", strerror(-r));
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen ret = EXIT_FAILURE;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen goto finish;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = timedatectl_main(bus, argc, argv);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen ret = r < 0 ? EXIT_FAILURE : r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenfinish:
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen pager_close();
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return ret;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen