blob: 209d1d56011ddedcfd8a8e4e822bf1dfc29d9786 [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 Vlasenkob097a842018-12-28 03:20:17 +010014//config: bool "adjtimex (4.7 kb)"
Denys Vlasenkofb4da162016-11-22 23:14:24 +010015//config: default y
Denys Vlasenkofb4da162016-11-22 23:14:24 +010016//config: help
Denys Vlasenko72089cf2017-07-21 09:50:55 +020017//config: Adjtimex reads and optionally sets adjustment parameters for
18//config: the Linux clock adjustment algorithm.
Mark Whitley6f932772001-03-20 19:18:10 +000019
Denys Vlasenkoed7d1182017-08-06 20:00:21 +020020//applet:IF_ADJTIMEX(APPLET_NOFORK(adjtimex, adjtimex, BB_DIR_SBIN, BB_SUID_DROP, adjtimex))
Denys Vlasenkof88e3bf2016-11-22 23:54:17 +010021
22//kbuild:lib-$(CONFIG_ADJTIMEX) += adjtimex.o
23
Pere Orga5bc8c002011-04-11 03:29:49 +020024//usage:#define adjtimex_trivial_usage
Denys Vlasenko5d553bc2020-12-13 19:18:28 +010025//usage: "[-q] [-o OFS] [-f FREQ] [-p TCONST] [-t TICK]"
Pere Orga5bc8c002011-04-11 03:29:49 +020026//usage:#define adjtimex_full_usage "\n\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +020027//usage: "Read or set kernel time variables. See adjtimex(2)\n"
Pere Orga5bc8c002011-04-11 03:29:49 +020028//usage: "\n -q Quiet"
29//usage: "\n -o OFF Time offset, microseconds"
30//usage: "\n -f FREQ Frequency adjust, integer kernel units (65536 is 1ppm)"
Pere Orga5bc8c002011-04-11 03:29:49 +020031//usage: "\n -t TICK Microseconds per tick, usually 10000"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +020032//usage: "\n (positive -t or -f values make clock run faster)"
Pere Orga5bc8c002011-04-11 03:29:49 +020033//usage: "\n -p TCONST"
34
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000035#include "libbb.h"
Denys Vlasenko8f6ce092011-07-08 08:34:28 +020036#ifdef __BIONIC__
37# include <linux/timex.h>
38#else
39# include <sys/timex.h>
40#endif
Mark Whitley6f932772001-03-20 19:18:10 +000041
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020042static const uint16_t statlist_bit[] ALIGN2 = {
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000043 STA_PLL,
44 STA_PPSFREQ,
45 STA_PPSTIME,
46 STA_FLL,
47 STA_INS,
48 STA_DEL,
49 STA_UNSYNC,
50 STA_FREQHOLD,
51 STA_PPSSIGNAL,
52 STA_PPSJITTER,
53 STA_PPSWANDER,
54 STA_PPSERROR,
55 STA_CLOCKERR,
56 0
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000057};
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020058static const char statlist_name[] ALIGN1 =
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000059 "PLL" "\0"
60 "PPSFREQ" "\0"
61 "PPSTIME" "\0"
62 "FFL" "\0"
63 "INS" "\0"
64 "DEL" "\0"
65 "UNSYNC" "\0"
66 "FREQHOLD" "\0"
67 "PPSSIGNAL" "\0"
68 "PPSJITTER" "\0"
69 "PPSWANDER" "\0"
70 "PPSERROR" "\0"
71 "CLOCKERR"
72;
Mark Whitley6f932772001-03-20 19:18:10 +000073
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020074static const char ret_code_descript[] ALIGN1 =
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000075 "clock synchronized" "\0"
76 "insert leap second" "\0"
77 "delete leap second" "\0"
78 "leap second in progress" "\0"
79 "leap second has occurred" "\0"
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000080 "clock not synchronized"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000081;
Mark Whitley6f932772001-03-20 19:18:10 +000082
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000083int adjtimex_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +010084int adjtimex_main(int argc UNUSED_PARAM, char **argv)
Mark Whitley6f932772001-03-20 19:18:10 +000085{
Denis Vlasenko109d21f2006-09-22 08:47:54 +000086 enum {
87 OPT_quiet = 0x1
88 };
Denis Vlasenko67b23e62006-10-03 21:00:06 +000089 unsigned opt;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000090 char *opt_o, *opt_f, *opt_p, *opt_t;
Mark Whitley6f932772001-03-20 19:18:10 +000091 struct timex txc;
Denys Vlasenkoc8e29312017-08-06 19:46:21 +020092 int ret;
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +000093 const char *descript;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000094
Denys Vlasenkoc8e29312017-08-06 19:46:21 +020095 memset(&txc, 0, sizeof(txc));
96
Denys Vlasenko22542ec2017-08-08 21:55:02 +020097 opt = getopt32(argv, "^" "qo:f:p:t:"
98 "\0" "=0"/*no valid non-option args*/,
99 &opt_o, &opt_f, &opt_p, &opt_t
100 );
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000101 //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
Denys Vlasenkoed7d1182017-08-06 20:00:21 +0200119 /* It's NOFORK applet because the code is very simple:
120 * just some printf. No opens, no allocs.
121 * If you need to make it more complex, feel free to downgrade to NOEXEC
122 */
123
Mark Whitley6f932772001-03-20 19:18:10 +0000124 ret = adjtimex(&txc);
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200125 if (ret < 0)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000126 bb_perror_nomsg_and_die();
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000127
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000128 if (!(opt & OPT_quiet)) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200129 const char *sep;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000130 const char *name;
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200131 int i;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000132
Mark Whitley6f932772001-03-20 19:18:10 +0000133 printf(
134 " mode: %d\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200135 "-o offset: %ld us\n"
136 "-f freq.adjust: %ld (65536 = 1ppm)\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000137 " maxerror: %ld\n"
138 " esterror: %ld\n"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000139 " status: %d (",
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200140 txc.modes, txc.offset, txc.freq, txc.maxerror,
141 txc.esterror, txc.status
142 );
Mark Whitley6f932772001-03-20 19:18:10 +0000143
144 /* representative output of next code fragment:
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200145 * "PLL | PPSTIME"
146 */
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000147 name = statlist_name;
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200148 sep = "";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000149 for (i = 0; statlist_bit[i]; i++) {
150 if (txc.status & statlist_bit[i]) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200151 printf("%s%s", sep, name);
152 sep = " | ";
Mark Whitley6f932772001-03-20 19:18:10 +0000153 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000154 name += strlen(name) + 1;
Mark Whitley6f932772001-03-20 19:18:10 +0000155 }
156
157 descript = "error";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000158 if (ret <= 5)
159 descript = nth_string(ret_code_descript, ret);
160 printf(")\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000161 "-p timeconstant: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200162 " precision: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000163 " tolerance: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200164 "-t tick: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000165 " time.tv_sec: %ld\n"
166 " time.tv_usec: %ld\n"
167 " return value: %d (%s)\n",
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200168 txc.constant,
169 txc.precision, txc.tolerance, txc.tick,
170 (long)txc.time.tv_sec, (long)txc.time.tv_usec,
171 ret, descript
172 );
Mark Whitley6f932772001-03-20 19:18:10 +0000173 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000174
175 return 0;
Mark Whitley6f932772001-03-20 19:18:10 +0000176}