timedatectl.c revision 857a493d55f94731394e4d9f61ffce661858e9a0
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
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
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <stdlib.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <stdbool.h>
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include <unistd.h>
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen#include <getopt.h>
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen#include <string.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include <sys/timex.h>
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen#include "dbus-common.h"
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen#include "util.h"
d122f9ee3a0e3c02ff8100a3dcd1866e90a6537aTom Gundersen#include "spawn-polkit-agent.h"
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen#include "build.h"
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen#include "hwclock.h"
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen#include "strv.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen#include "pager.h"
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic bool arg_adjust_system_clock = false;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic bool arg_no_pager = false;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersenstatic enum transport {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen TRANSPORT_NORMAL,
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen TRANSPORT_SSH,
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen TRANSPORT_POLKIT
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen} arg_transport = TRANSPORT_NORMAL;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic bool arg_ask_password = true;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic const 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();
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen}
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersenstatic void polkit_agent_open_if_enabled(void) {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen /* Open the polkit agent as a child process if necessary */
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen if (!arg_ask_password)
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen return;
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen polkit_agent_open();
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen}
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersentypedef struct StatusInfo {
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen const char *timezone;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen bool local_rtc;
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen bool ntp;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen} StatusInfo;
756775814cf69471f74ce853745bba69f2ba94efThomas Hindoe Paaboel Andersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersenstatic bool ntp_synced(void) {
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen struct timex txc;
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen
7c16313f11e3953f3fe4dbf544f2d36f58d14138Tom Gundersen zero(txc);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (adjtimex(&txc) < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return false;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (txc.status & STA_UNSYNC)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return false;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return true;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen}
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic void print_status_info(StatusInfo *i) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen usec_t n;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char b[FORMAT_TIMESTAMP_MAX];
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen struct tm tm;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen time_t sec;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen int r;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(i);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen n = now(CLOCK_REALTIME);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen sec = (time_t) (n / USEC_PER_SEC);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen zero(tm);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)) > 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char_array_0(b);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen printf(" Local time: %s\n", b);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen zero(tm);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)) > 0);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen char_array_0(b);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen printf(" Universal time: %s\n", b);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen zero(tm);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen r = hwclock_get_time(&tm);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (r >= 0) {
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen /* Calculcate the week-day */
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen mktime(&tm);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert_se(strftime(b, sizeof(b), "%a, %Y-%m-%d %H:%M:%S", &tm) > 0);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt char_array_0(b);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt printf(" RTC time: %s\n", b);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen printf(" Timezone: %s\n"
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen " NTP enabled: %s\n"
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen "NTP synchronized: %s\n"
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen " RTC in local TZ: %s\n",
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen strna(i->timezone),
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen yes_no(i->ntp),
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen yes_no(ntp_synced()),
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen yes_no(i->local_rtc));
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen if (i->local_rtc)
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering fputs("\n" ANSI_HIGHLIGHT_ON
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);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersenstatic int status_property(const char *name, DBusMessageIter *iter, StatusInfo *i) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering assert(name);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen assert(iter);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering switch (dbus_message_iter_get_arg_type(iter)) {
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering case DBUS_TYPE_STRING: {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering const char *s;
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering dbus_message_iter_get_basic(iter, &s);
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (!isempty(s)) {
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering if (streq(name, "Timezone"))
3bdace9bf779ce051f00c14914b35c3a26164aa9Lennart Poettering i->timezone = s;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen break;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen case DBUS_TYPE_BOOLEAN: {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen dbus_bool_t b;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen dbus_message_iter_get_basic(iter, &b);
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen if (streq(name, "LocalRTC"))
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen i->local_rtc = b;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen else if (streq(name, "NTP"))
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen i->ntp = b;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen return 0;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen}
20af7091de0cdf92bf299addfc3f96c3ef805bd8Tom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersenstatic int show_status(DBusConnection *bus, char **args, unsigned n) {
3a864fe4a894745ac61f1ecabd7cadf04139a284Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt const char *interface = "";
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen int r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DBusMessageIter iter, sub, sub2, sub3;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen StatusInfo info;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen assert(args);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen r = bus_method_call_with_reply(
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen bus,
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen "org.freedesktop.timedate1",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "/org/freedesktop/timedate1",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "org.freedesktop.DBus.Properties",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen "GetAll",
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen &reply,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen NULL,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DBUS_TYPE_STRING, &interface,
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen DBUS_TYPE_INVALID);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (r < 0)
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return r;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (!dbus_message_iter_init(reply, &iter) ||
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 log_error("Failed to parse reply.");
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return -EIO;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen zero(info);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen dbus_message_iter_recurse(&iter, &sub);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen const char *name;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_DICT_ENTRY) {
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen log_error("Failed to parse reply.");
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen return -EIO;
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen }
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen dbus_message_iter_recurse(&sub, &sub2);
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen
b44cd8821087f2afebf85fec5b588f5720a9415cTom Gundersen if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &name, true) < 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_error("Failed to parse reply.");
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return -EIO;
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_VARIANT) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_error("Failed to parse reply.");
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return -EIO;
8de4a226c71ef43e652274b33b5d19211a44ac7bTom Gundersen }
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen dbus_message_iter_recurse(&sub2, &sub3);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen r = status_property(name, &sub3, &info);
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen if (r < 0) {
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen log_error("Failed to parse reply.");
ff734080aa02cd70b13bc0fdeec4a5886166163aTom Gundersen return r;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dbus_message_iter_next(&sub);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen print_status_info(&info);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
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 usec_t t;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dbus_int64_t u;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen int r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(args);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(n == 2);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen polkit_agent_open_if_enabled();
a6f1e036de8f212f33ead7f5387c297afd8be26eTom 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 u = (dbus_uint64_t) t;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return bus_method_call_with_reply(
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetTime",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &reply,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen NULL,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_INT64, &u,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &relative,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &interactive,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_INVALID);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_timezone(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dbus_bool_t interactive = true;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(args);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(n == 2);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen polkit_agent_open_if_enabled();
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return bus_method_call_with_reply(
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetTimezone",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &reply,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen NULL,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_STRING, &args[1],
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &interactive,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_INVALID);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_local_rtc(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dbus_bool_t interactive = true, b, q;
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_boolean(args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse local RTC setting: %s", args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen b = r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen q = arg_adjust_system_clock;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return bus_method_call_with_reply(
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetLocalRTC",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &reply,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen NULL,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &b,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &q,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &interactive,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_INVALID);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int set_ntp(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen dbus_bool_t interactive = true, b;
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_boolean(args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (r < 0) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to parse NTP setting: %s", args[1]);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen b = r;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return bus_method_call_with_reply(
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen bus,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "/org/freedesktop/timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "org.freedesktop.timedate1",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen "SetNTP",
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen &reply,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen NULL,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &b,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_BOOLEAN, &interactive,
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen DBUS_TYPE_INVALID);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen}
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersenstatic int list_timezones(DBusConnection *bus, char **args, unsigned n) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_fclose_ FILE *f = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen _cleanup_strv_free_ char **zones = NULL;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen size_t n_zones = 0;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen char **i;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(args);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen assert(n == 1);
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen f = fopen("/usr/share/zoneinfo/zone.tab", "re");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!f) {
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to open timezone database: %m");
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen for (;;) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen char l[LINE_MAX], *p, **z, *w;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen size_t k;
d6bd972d061af306ede2affd2c9340a1660f7996Tom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen if (!fgets(l, sizeof(l), f)) {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (feof(f))
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen break;
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen log_error("Failed to read timezone database: %m");
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen return -errno;
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen }
969b009d9416806911b9b52e7e7bc619c0c1a931Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen p = strstrip(l);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (isempty(p) || *p == '#')
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen continue;
1231c4d238844e77018caf5b5852f01d96373c47Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* Skip over country code */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen p += strcspn(p, WHITESPACE);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen p += strspn(p, WHITESPACE);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen /* Skip over coordinates */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen p += strcspn(p, WHITESPACE);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen p += strspn(p, WHITESPACE);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen /* Found timezone name */
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen k = strcspn(p, WHITESPACE);
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (k <= 0)
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams continue;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen w = strndup(p, k);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (!w)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return log_oom();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen z = realloc(zones, sizeof(char*) * (n_zones + 2));
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen if (!z) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen free(w);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return log_oom();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen zones = z;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen zones[n_zones++] = w;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen }
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen if (zones)
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen zones[n_zones] = NULL;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen pager_open_if_enabled();
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen strv_sort(zones);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen STRV_FOREACH(i, zones)
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen puts(*i);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return 0;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen}
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int help(void) {
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen printf("%s [OPTIONS...] COMMAND ...\n\n"
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 Gundersen program_invocation_short_name);
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen return 0;
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen}
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersenstatic int parse_argv(int argc, char *argv[]) {
4dc355680460fdc8e0d590d8572dff1b6a257d88Tom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen enum {
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen ARG_VERSION = 0x100,
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen ARG_NO_PAGER,
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen ARG_ADJUST_SYSTEM_CLOCK,
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen ARG_NO_ASK_PASSWORD
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen };
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen static const struct option options[] = {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "help", no_argument, NULL, 'h' },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "version", no_argument, NULL, ARG_VERSION },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "no-pager", no_argument, NULL, ARG_NO_PAGER },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "host", required_argument, NULL, 'H' },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "privileged", no_argument, NULL, 'P' },
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen { "adjust-system-clock", no_argument, NULL, ARG_ADJUST_SYSTEM_CLOCK },
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen { NULL, 0, NULL, 0 }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen };
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen int c;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen assert(argc >= 0);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen assert(argv);
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen while ((c = getopt_long(argc, argv, "+hH:P", options, NULL)) >= 0) {
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen switch (c) {
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen case 'h':
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen help();
59b8f6b628145586e87b8a4f6e29c755ad7d61edTom Gundersen return 0;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering case ARG_VERSION:
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering puts(PACKAGE_STRING);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering puts(DISTRIBUTION);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering puts(SYSTEMD_FEATURES);
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering return 0;
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering case 'P':
8eb9058dc1f99a5eb9b8726a978fcc0720837a10Lennart Poettering arg_transport = TRANSPORT_POLKIT;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen break;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen case 'H':
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen arg_transport = TRANSPORT_SSH;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen arg_host = optarg;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen break;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen case ARG_ADJUST_SYSTEM_CLOCK:
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen arg_adjust_system_clock = true;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen break;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen case ARG_NO_PAGER:
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen arg_no_pager = true;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen break;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen case '?':
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen return -EINVAL;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen default:
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen log_error("Unknown option code %c", c);
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen return -EINVAL;
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
bd57b45029ff25067704c9538e79f31e71c10045Tom Gundersen }
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen return 1;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen}
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersenstatic int timedatectl_main(DBusConnection *bus, int argc, char *argv[], DBusError *error) {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen static const struct {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen const char* verb;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen const enum {
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen MORE,
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen LESS,
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen EQUAL
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen } argc_cmp;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen const int argc;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen int (* const dispatch)(DBusConnection *bus, char **args, unsigned n);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams } verbs[] = {
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams { "status", LESS, 1, show_status },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen { "set-time", EQUAL, 2, set_time },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen { "set-timezone", EQUAL, 2, set_timezone },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen { "list-timezones", EQUAL, 1, list_timezones },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen { "set-local-rtc", EQUAL, 2, set_local_rtc },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen { "set-ntp", EQUAL, 2, set_ntp, },
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen };
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen int left;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen unsigned i;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen assert(argc >= 0);
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen assert(argv);
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen assert(error);
c15fb62a731f1a457af94e60ac6a4d23f219a8f6Thomas Hindoe Paaboel Andersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen left = argc - optind;
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen if (left <= 0)
527503444ef24ae03c73cf85128c7acbb1146f3cTom Gundersen /* Special rule: no arguments means "status" */
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen i = 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen else {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (streq(argv[optind], "help")) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen help();
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return 0;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen for (i = 0; i < ELEMENTSOF(verbs); i++)
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen if (streq(argv[optind], verbs[i].verb))
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen break;
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen if (i >= ELEMENTSOF(verbs)) {
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen log_error("Unknown operation %s", argv[optind]);
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen return -EINVAL;
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen }
2dead8129f7b6fe644e17e1dc1739bebacfe1364Tom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen switch (verbs[i].argc_cmp) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen case EQUAL:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (left != verbs[i].argc) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error("Invalid number of arguments.");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return -EINVAL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen break;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen case MORE:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (left < verbs[i].argc) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error("Too few arguments.");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return -EINVAL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen break;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen case LESS:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (left > verbs[i].argc) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error("Too many arguments.");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return -EINVAL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen break;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen default:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert_not_reached("Unknown comparison operator.");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (!bus) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_error("Failed to get D-Bus connection: %s", error->message);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return -EIO;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen return verbs[i].dispatch(bus, argv + optind, left);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen}
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersenint main(int argc, char *argv[]) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen int r, retval = EXIT_FAILURE;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen DBusConnection *bus = NULL;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen DBusError error;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen dbus_error_init(&error);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_parse_environment();
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen log_open();
e2acdb6b0f68d9b4152708a9f21bf9e11f8b9e7eTorstein Husebø
a6f1e036de8f212f33ead7f5387c297afd8be26eTom Gundersen r = parse_argv(argc, argv);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (r < 0)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen goto finish;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen else if (r == 0) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen retval = EXIT_SUCCESS;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen goto finish;
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen }
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (arg_transport == TRANSPORT_NORMAL)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen else if (arg_transport == TRANSPORT_POLKIT)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen bus_connect_system_polkit(&bus, &error);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen else if (arg_transport == TRANSPORT_SSH)
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen bus_connect_system_ssh(NULL, arg_host, &bus, &error);
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen else
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen assert_not_reached("Uh, invalid transport...");
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen r = timedatectl_main(bus, argc, argv, &error);
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen retval = r < 0 ? EXIT_FAILURE : r;
c7d9ffe6d629cb5b34dd749e4a88b190b11a0f48Tom Gundersen
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersenfinish:
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen if (bus) {
816e2e7af96886e4a43194042ef61ba9fec2c77dTom Gundersen dbus_connection_flush(bus);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen dbus_connection_close(bus);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen dbus_connection_unref(bus);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen }
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen dbus_error_free(&error);
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen dbus_shutdown();
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen pager_close();
500792d8180c9a11d65f107cdc79dea21b2964c4Tom Gundersen
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen return retval;
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen}
87322b3aee0dc649ff1ae7a403dcc9d7305baba2Tom Gundersen