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