timedatectl.c revision 857a493d55f94731394e4d9f61ffce661858e9a0
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen This file is part of systemd.
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen Copyright 2012 Lennart Poettering
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 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 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/>.
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic bool arg_adjust_system_clock = false;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic bool arg_no_pager = false;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic bool arg_ask_password = true;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic void pager_open_if_enabled(void) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersenstatic void polkit_agent_open_if_enabled(void) {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen /* Open the polkit agent as a child process if necessary */
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersentypedef struct StatusInfo {
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersenstatic bool ntp_synced(void) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return false;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return false;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r >= 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen /* Calculcate the week-day */
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S", &tm) > 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen " NTP enabled: %s\n"
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen "NTP synchronized: %s\n"
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen " RTC in local TZ: %s\n",
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering "Warning: The RTC is configured to maintain time in the local time zone. This\n"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen " mode is not fully supported and will create various problems with time\n"
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering " zone changes and daylight saving adjustments. If at all possible use\n"
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering " RTC in UTC, by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic int status_property(const char *name, DBusMessageIter *iter, StatusInfo *i) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering switch (dbus_message_iter_get_arg_type(iter)) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering const char *s;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersenstatic int show_status(DBusConnection *bus, char **args, unsigned n) {
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "org.freedesktop.DBus.Properties",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_time(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dbus_bool_t relative = false, interactive = true;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse time specification: %s", args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_timezone(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetTimezone",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_local_rtc(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse local RTC setting: %s", args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetLocalRTC",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_ntp(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse NTP setting: %s", args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int list_timezones(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen f = fopen("/usr/share/zoneinfo/zone.tab", "re");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to open timezone database: %m");
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen char l[LINE_MAX], *p, **z, *w;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!fgets(l, sizeof(l), f)) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to read timezone database: %m");
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* Skip over country code */
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen /* Skip over coordinates */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* Found timezone name */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen z = realloc(zones, sizeof(char*) * (n_zones + 2));
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int help(void) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen "Query or change system time and date settings.\n\n"
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen " -h --help Show this help\n"
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen " --version Show package version\n"
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen " --adjust-system-clock\n"
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen " Adjust system clock when changing local RTC mode\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " --no-pager Do not pipe output into a pager\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " --no-ask-password Do not prompt for password\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " -H --host=[USER@]HOST Operate on remote host\n\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen "Commands:\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " status Show current time settings\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " set-time TIME Set system time\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " set-timezone ZONE Set system timezone\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " list-timezones Show known timezones\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " set-local-rtc BOOL Control whether RTC is in local time\n"
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen " set-ntp BOOL Control whether NTP is enabled\n",
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int parse_argv(int argc, char *argv[]) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "version", no_argument, NULL, ARG_VERSION },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "no-pager", no_argument, NULL, ARG_NO_PAGER },
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen while ((c = getopt_long(argc, argv, "+hH:P", options, NULL)) >= 0) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersenstatic int timedatectl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen static const struct {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen { "list-timezones", EQUAL, 1, list_timezones },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen /* Special rule: no arguments means "status" */
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Unknown operation %s", argv[optind]);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert_not_reached("Unknown comparison operator.");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error("Failed to get D-Bus connection: %s", error->message);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return verbs[i].dispatch(bus, argv + optind, left);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen else if (r == 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen bus_connect_system_ssh(NULL, arg_host, &bus, &error);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert_not_reached("Uh, invalid transport...");