blob: 8ca90d58a9ccee2da364aa3776d600da3f4aeebe [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
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 Vlasenkoed7d1182017-08-06 20:00:21 +020021//applet:IF_ADJTIMEX(APPLET_NOFORK(adjtimex, adjtimex, BB_DIR_SBIN, BB_SUID_DROP, adjtimex))
Denys Vlasenkof88e3bf2016-11-22 23:54:17 +010022
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 Vlasenko22542ec2017-08-08 21:55:02 +020098 opt = getopt32(argv, "^" "qo:f:p:t:"
99 "\0" "=0"/*no valid non-option args*/,
100 &opt_o, &opt_f, &opt_p, &opt_t
101 );
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000102 //if (opt & 0x1) // -q
103 if (opt & 0x2) { // -o
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000104 txc.offset = xatol(opt_o);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000105 txc.modes |= ADJ_OFFSET_SINGLESHOT;
106 }
107 if (opt & 0x4) { // -f
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000108 txc.freq = xatol(opt_f);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000109 txc.modes |= ADJ_FREQUENCY;
110 }
111 if (opt & 0x8) { // -p
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000112 txc.constant = xatol(opt_p);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000113 txc.modes |= ADJ_TIMECONST;
114 }
115 if (opt & 0x10) { // -t
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000116 txc.tick = xatol(opt_t);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000117 txc.modes |= ADJ_TICK;
Mark Whitley6f932772001-03-20 19:18:10 +0000118 }
Mark Whitley6f932772001-03-20 19:18:10 +0000119
Denys Vlasenkoed7d1182017-08-06 20:00:21 +0200120 /* It's NOFORK applet because the code is very simple:
121 * just some printf. No opens, no allocs.
122 * If you need to make it more complex, feel free to downgrade to NOEXEC
123 */
124
Mark Whitley6f932772001-03-20 19:18:10 +0000125 ret = adjtimex(&txc);
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200126 if (ret < 0)
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000127 bb_perror_nomsg_and_die();
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000128
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000129 if (!(opt & OPT_quiet)) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200130 const char *sep;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000131 const char *name;
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200132 int i;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000133
Mark Whitley6f932772001-03-20 19:18:10 +0000134 printf(
135 " mode: %d\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200136 "-o offset: %ld us\n"
137 "-f freq.adjust: %ld (65536 = 1ppm)\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000138 " maxerror: %ld\n"
139 " esterror: %ld\n"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000140 " status: %d (",
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200141 txc.modes, txc.offset, txc.freq, txc.maxerror,
142 txc.esterror, txc.status
143 );
Mark Whitley6f932772001-03-20 19:18:10 +0000144
145 /* representative output of next code fragment:
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200146 * "PLL | PPSTIME"
147 */
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000148 name = statlist_name;
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200149 sep = "";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000150 for (i = 0; statlist_bit[i]; i++) {
151 if (txc.status & statlist_bit[i]) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200152 printf("%s%s", sep, name);
153 sep = " | ";
Mark Whitley6f932772001-03-20 19:18:10 +0000154 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000155 name += strlen(name) + 1;
Mark Whitley6f932772001-03-20 19:18:10 +0000156 }
157
158 descript = "error";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000159 if (ret <= 5)
160 descript = nth_string(ret_code_descript, ret);
161 printf(")\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000162 "-p timeconstant: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200163 " precision: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000164 " tolerance: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200165 "-t tick: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000166 " time.tv_sec: %ld\n"
167 " time.tv_usec: %ld\n"
168 " return value: %d (%s)\n",
Denys Vlasenkoc8e29312017-08-06 19:46:21 +0200169 txc.constant,
170 txc.precision, txc.tolerance, txc.tick,
171 (long)txc.time.tv_sec, (long)txc.time.tv_usec,
172 ret, descript
173 );
Mark Whitley6f932772001-03-20 19:18:10 +0000174 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000175
176 return 0;
Mark Whitley6f932772001-03-20 19:18:10 +0000177}