blob: a39c4f5cfa464514c2ea5b5a1111e8a61e0bddc6 [file] [log] [blame]
Bernhard Reutner-Fischerc89982d2006-06-03 19:49:21 +00001/* vi: set sw=4 ts=4: */
Mark Whitley6f932772001-03-20 19:18:10 +00002/*
Denys Vlasenko95f79532017-08-02 14:26:33 +02003 * adjtimex.c - read, and possibly modify, the Linux kernel 'timex' variables.
Mark Whitley6f932772001-03-20 19:18:10 +00004 *
5 * Originally written: October 1997
6 * Last hack: March 2001
7 * Copyright 1997, 2000, 2001 Larry Doolittle <LRDoolittle@lbl.gov>
8 *
Mark Whitley6f932772001-03-20 19:18:10 +00009 * busyboxed 20 March 2001, Larry Doolittle <ldoolitt@recycle.lbl.gov>
Bernhard Reutner-Fischerc89982d2006-06-03 19:49:21 +000010 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +020011 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Mark Whitley6f932772001-03-20 19:18:10 +000012 */
Denys Vlasenkofb4da162016-11-22 23:14:24 +010013//config:config ADJTIMEX
Denys Vlasenko4eed2c62017-07-18 22:01:24 +020014//config: bool "adjtimex (4.5 kb)"
Denys Vlasenkofb4da162016-11-22 23:14:24 +010015//config: default y
16//config: select PLATFORM_LINUX
17//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020018//config: Adjtimex reads and optionally sets adjustment parameters for
19//config: the Linux clock adjustment algorithm.
Mark Whitley6f932772001-03-20 19:18:10 +000020
Denys Vlasenkof88e3bf2016-11-22 23:54:17 +010021//applet:IF_ADJTIMEX(APPLET(adjtimex, BB_DIR_SBIN, BB_SUID_DROP))
22
23//kbuild:lib-$(CONFIG_ADJTIMEX) += adjtimex.o
24
Pere Orga5bc8c002011-04-11 03:29:49 +020025//usage:#define adjtimex_trivial_usage
26//usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
27//usage:#define adjtimex_full_usage "\n\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +020028//usage: "Read or set kernel time variables. See adjtimex(2)\n"
Pere Orga5bc8c002011-04-11 03:29:49 +020029//usage: "\n -q Quiet"
30//usage: "\n -o OFF Time offset, microseconds"
31//usage: "\n -f FREQ Frequency adjust, integer kernel units (65536 is 1ppm)"
Pere Orga5bc8c002011-04-11 03:29:49 +020032//usage: "\n -t TICK Microseconds per tick, usually 10000"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +020033//usage: "\n (positive -t or -f values make clock run faster)"
Pere Orga5bc8c002011-04-11 03:29:49 +020034//usage: "\n -p TCONST"
35
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000036#include "libbb.h"
Denys Vlasenko8f6ce092011-07-08 08:34:28 +020037#ifdef __BIONIC__
38# include <linux/timex.h>
39#else
40# include <sys/timex.h>
41#endif
Mark Whitley6f932772001-03-20 19:18:10 +000042
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020043static const uint16_t statlist_bit[] ALIGN2 = {
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000044 STA_PLL,
45 STA_PPSFREQ,
46 STA_PPSTIME,
47 STA_FLL,
48 STA_INS,
49 STA_DEL,
50 STA_UNSYNC,
51 STA_FREQHOLD,
52 STA_PPSSIGNAL,
53 STA_PPSJITTER,
54 STA_PPSWANDER,
55 STA_PPSERROR,
56 STA_CLOCKERR,
57 0
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000058};
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020059static const char statlist_name[] ALIGN1 =
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000060 "PLL" "\0"
61 "PPSFREQ" "\0"
62 "PPSTIME" "\0"
63 "FFL" "\0"
64 "INS" "\0"
65 "DEL" "\0"
66 "UNSYNC" "\0"
67 "FREQHOLD" "\0"
68 "PPSSIGNAL" "\0"
69 "PPSJITTER" "\0"
70 "PPSWANDER" "\0"
71 "PPSERROR" "\0"
72 "CLOCKERR"
73;
Mark Whitley6f932772001-03-20 19:18:10 +000074
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020075static const char ret_code_descript[] ALIGN1 =
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000076 "clock synchronized" "\0"
77 "insert leap second" "\0"
78 "delete leap second" "\0"
79 "leap second in progress" "\0"
80 "leap second has occurred" "\0"
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000081 "clock not synchronized"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000082;
Mark Whitley6f932772001-03-20 19:18:10 +000083
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000084int adjtimex_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +010085int adjtimex_main(int argc UNUSED_PARAM, char **argv)
Mark Whitley6f932772001-03-20 19:18:10 +000086{
Denis Vlasenko109d21f2006-09-22 08:47:54 +000087 enum {
88 OPT_quiet = 0x1
89 };
Denis Vlasenko67b23e62006-10-03 21:00:06 +000090 unsigned opt;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000091 char *opt_o, *opt_f, *opt_p, *opt_t;
Mark Whitley6f932772001-03-20 19:18:10 +000092 struct timex txc;
Denys Vlasenkoc8e29312017-08-06 19:46:21 +020093 int ret;
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +000094 const char *descript;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000095
Denys Vlasenkoc8e29312017-08-06 19:46:21 +020096 memset(&txc, 0, sizeof(txc));
97
Denys Vlasenkoe992bae2009-11-28 15:18:53 +010098 opt_complementary = "=0"; /* no valid non-option parameters */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +000099 opt = getopt32(argv, "qo:f:p:t:",
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000100 &opt_o, &opt_f, &opt_p, &opt_t);
101 //if (opt & 0x1) // -q
102 if (opt & 0x2) { // -o
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000103 txc.offset = xatol(opt_o);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000104 txc.modes |= ADJ_OFFSET_SINGLESHOT;
105 }
106 if (opt & 0x4) { // -f
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000107 txc.freq = xatol(opt_f);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000108 txc.modes |= ADJ_FREQUENCY;
109 }
110 if (opt & 0x8) { // -p
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000111 txc.constant = xatol(opt_p);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000112 txc.modes |= ADJ_TIMECONST;
113 }
114 if (opt & 0x10) { // -t
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000115 txc.tick = xatol(opt_t);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000116 txc.modes |= ADJ_TICK;
Mark Whitley6f932772001-03-20 19:18:10 +0000117 }
Mark Whitley6f932772001-03-20 19:18:10 +0000118
119 ret = adjtimex(&txc);
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200120 if (ret < 0)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000121 bb_perror_nomsg_and_die();
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000122
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000123 if (!(opt & OPT_quiet)) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200124 const char *sep;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000125 const char *name;
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200126 int i;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000127
Mark Whitley6f932772001-03-20 19:18:10 +0000128 printf(
129 " mode: %d\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200130 "-o offset: %ld us\n"
131 "-f freq.adjust: %ld (65536 = 1ppm)\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000132 " maxerror: %ld\n"
133 " esterror: %ld\n"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000134 " status: %d (",
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200135 txc.modes, txc.offset, txc.freq, txc.maxerror,
136 txc.esterror, txc.status
137 );
Mark Whitley6f932772001-03-20 19:18:10 +0000138
139 /* representative output of next code fragment:
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200140 * "PLL | PPSTIME"
141 */
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000142 name = statlist_name;
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200143 sep = "";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000144 for (i = 0; statlist_bit[i]; i++) {
145 if (txc.status & statlist_bit[i]) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200146 printf("%s%s", sep, name);
147 sep = " | ";
Mark Whitley6f932772001-03-20 19:18:10 +0000148 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000149 name += strlen(name) + 1;
Mark Whitley6f932772001-03-20 19:18:10 +0000150 }
151
152 descript = "error";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000153 if (ret <= 5)
154 descript = nth_string(ret_code_descript, ret);
155 printf(")\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000156 "-p timeconstant: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200157 " precision: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000158 " tolerance: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200159 "-t tick: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000160 " time.tv_sec: %ld\n"
161 " time.tv_usec: %ld\n"
162 " return value: %d (%s)\n",
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200163 txc.constant,
164 txc.precision, txc.tolerance, txc.tick,
165 (long)txc.time.tv_sec, (long)txc.time.tv_usec,
166 ret, descript
167 );
Mark Whitley6f932772001-03-20 19:18:10 +0000168 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000169
170 return 0;
Mark Whitley6f932772001-03-20 19:18:10 +0000171}