diff --git a/Base/usr/share/man/man1/adjtime.md b/Base/usr/share/man/man1/adjtime.md new file mode 100644 index 0000000000..62346ced94 --- /dev/null +++ b/Base/usr/share/man/man1/adjtime.md @@ -0,0 +1,36 @@ +## Name + +adjtime - print remaining system clock adjustment, and optionally set it + +## Synopsis + +```sh +adjtime [options...] +``` + +## Description + +`adjtime -s delta_seconds` will smoothly adjust the system time by slowing it +down (if `delta_seconds` is negative) or speeding it up (if `delta_seconds` is +positive) by a fraction of a second. The larger `delta_seconds` is, the longer +this takes. If `delta_seconds` is set and a previous time adjustment is in +progress, the remaining adjustment is canceled. That is, if `adjtime -s 1` is +called, and then `adjtime -s 1` is called again later when only 0.3s of the +first `adjtime` call have been applied yet, the clock is adjusted by 1.3 +seconds total, not by 2 seconds. + +`adjtime` also prints the remaining system clock adjustment. + +## Options + +* `-s delta_seconds`, `--set delta_seconds`: Adjust system time by + `delta_seconds`. Must be superuser. + +## Examples + +```sh +# adjtime -s 4.2 +4.2 +# sleep 1 && adjtime +4.1 +``` diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index f341ab722f..ca914b3e68 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -76,6 +76,10 @@ if (BUILD_LAGOM) target_link_libraries(TestJson Lagom) target_link_libraries(TestJson stdc++) + add_executable(adjtime_lagom ../../Userland/adjtime.cpp) + set_target_properties(adjtime_lagom PROPERTIES OUTPUT_NAME adjtime) + target_link_libraries(adjtime_lagom Lagom) + add_executable(js_lagom ../../Userland/js.cpp) set_target_properties(js_lagom PROPERTIES OUTPUT_NAME js) target_link_libraries(js_lagom Lagom) diff --git a/Userland/adjtime.cpp b/Userland/adjtime.cpp new file mode 100644 index 0000000000..810421bc98 --- /dev/null +++ b/Userland/adjtime.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, Nico Weber + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +int main(int argc, char** argv) +{ +#ifdef __serenity__ + if (pledge("stdio settime", nullptr) < 0) { + perror("pledge"); + return 1; + } +#endif + + Core::ArgsParser args_parser; + double delta = __builtin_nan(""); + args_parser.add_option(delta, "Adjust system time by this many seconds", "set", 's', "delta_seconds"); + args_parser.parse(argc, argv); + + if (__builtin_isnan(delta)) { +#ifdef __serenity__ + if (pledge("stdio", nullptr) < 0) { + perror("pledge"); + return 1; + } +#endif + } else { + long delta_us = static_cast(round(delta * 1'000'000)); + timeval delta_timeval; + delta_timeval.tv_sec = delta_us / 1'000'000; + delta_timeval.tv_usec = delta_us % 1'000'000; + if (delta_timeval.tv_usec < 0) { + delta_timeval.tv_sec--; + delta_timeval.tv_usec += 1'000'000; + } + if (adjtime(&delta_timeval, nullptr) < 0) { + perror("adjtime set"); + return 1; + } + } + + timeval remaining_delta_timeval; + if (adjtime(nullptr, &remaining_delta_timeval) < 0) { + perror("adjtime get"); + return 1; + } + double remaining_delta = remaining_delta_timeval.tv_sec + remaining_delta_timeval.tv_usec / 1'000'000.0; + printf("%f\n", remaining_delta); + + return 0; +}