blob: 058aa9a5cdc29c31a47d57167fe94b6138620f39 [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/*
3 * adjtimex.c - read, and possibly modify, the Linux kernel `timex' variables.
4 *
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 */
13
Pere Orga5bc8c002011-04-11 03:29:49 +020014//usage:#define adjtimex_trivial_usage
15//usage: "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
16//usage:#define adjtimex_full_usage "\n\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +020017//usage: "Read or set kernel time variables. See adjtimex(2)\n"
Pere Orga5bc8c002011-04-11 03:29:49 +020018//usage: "\n -q Quiet"
19//usage: "\n -o OFF Time offset, microseconds"
20//usage: "\n -f FREQ Frequency adjust, integer kernel units (65536 is 1ppm)"
Pere Orga5bc8c002011-04-11 03:29:49 +020021//usage: "\n -t TICK Microseconds per tick, usually 10000"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +020022//usage: "\n (positive -t or -f values make clock run faster)"
Pere Orga5bc8c002011-04-11 03:29:49 +020023//usage: "\n -p TCONST"
24
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000025#include "libbb.h"
Denys Vlasenko8f6ce092011-07-08 08:34:28 +020026#ifdef __BIONIC__
27# include <linux/timex.h>
28#else
29# include <sys/timex.h>
30#endif
Mark Whitley6f932772001-03-20 19:18:10 +000031
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020032static const uint16_t statlist_bit[] ALIGN2 = {
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000033 STA_PLL,
34 STA_PPSFREQ,
35 STA_PPSTIME,
36 STA_FLL,
37 STA_INS,
38 STA_DEL,
39 STA_UNSYNC,
40 STA_FREQHOLD,
41 STA_PPSSIGNAL,
42 STA_PPSJITTER,
43 STA_PPSWANDER,
44 STA_PPSERROR,
45 STA_CLOCKERR,
46 0
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000047};
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020048static const char statlist_name[] ALIGN1 =
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000049 "PLL" "\0"
50 "PPSFREQ" "\0"
51 "PPSTIME" "\0"
52 "FFL" "\0"
53 "INS" "\0"
54 "DEL" "\0"
55 "UNSYNC" "\0"
56 "FREQHOLD" "\0"
57 "PPSSIGNAL" "\0"
58 "PPSJITTER" "\0"
59 "PPSWANDER" "\0"
60 "PPSERROR" "\0"
61 "CLOCKERR"
62;
Mark Whitley6f932772001-03-20 19:18:10 +000063
Denys Vlasenko3e134eb2016-04-22 18:09:21 +020064static const char ret_code_descript[] ALIGN1 =
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000065 "clock synchronized" "\0"
66 "insert leap second" "\0"
67 "delete leap second" "\0"
68 "leap second in progress" "\0"
69 "leap second has occurred" "\0"
Denis Vlasenko6ca409e2007-08-12 20:58:27 +000070 "clock not synchronized"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000071;
Mark Whitley6f932772001-03-20 19:18:10 +000072
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +000073int adjtimex_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denys Vlasenkoe992bae2009-11-28 15:18:53 +010074int adjtimex_main(int argc UNUSED_PARAM, char **argv)
Mark Whitley6f932772001-03-20 19:18:10 +000075{
Denis Vlasenko109d21f2006-09-22 08:47:54 +000076 enum {
77 OPT_quiet = 0x1
78 };
Denis Vlasenko67b23e62006-10-03 21:00:06 +000079 unsigned opt;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000080 char *opt_o, *opt_f, *opt_p, *opt_t;
Mark Whitley6f932772001-03-20 19:18:10 +000081 struct timex txc;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +000082 int i, ret;
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +000083 const char *descript;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000084
Denys Vlasenkoe992bae2009-11-28 15:18:53 +010085 opt_complementary = "=0"; /* no valid non-option parameters */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +000086 opt = getopt32(argv, "qo:f:p:t:",
Denis Vlasenko109d21f2006-09-22 08:47:54 +000087 &opt_o, &opt_f, &opt_p, &opt_t);
Denys Vlasenkoe992bae2009-11-28 15:18:53 +010088 txc.modes = 0;
Denis Vlasenko109d21f2006-09-22 08:47:54 +000089 //if (opt & 0x1) // -q
90 if (opt & 0x2) { // -o
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +000091 txc.offset = xatol(opt_o);
Denis Vlasenko109d21f2006-09-22 08:47:54 +000092 txc.modes |= ADJ_OFFSET_SINGLESHOT;
93 }
94 if (opt & 0x4) { // -f
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +000095 txc.freq = xatol(opt_f);
Denis Vlasenko109d21f2006-09-22 08:47:54 +000096 txc.modes |= ADJ_FREQUENCY;
97 }
98 if (opt & 0x8) { // -p
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +000099 txc.constant = xatol(opt_p);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000100 txc.modes |= ADJ_TIMECONST;
101 }
102 if (opt & 0x10) { // -t
Denis Vlasenkodd2b2f72007-03-14 23:00:26 +0000103 txc.tick = xatol(opt_t);
Denis Vlasenko109d21f2006-09-22 08:47:54 +0000104 txc.modes |= ADJ_TICK;
Mark Whitley6f932772001-03-20 19:18:10 +0000105 }
Mark Whitley6f932772001-03-20 19:18:10 +0000106
107 ret = adjtimex(&txc);
108
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000109 if (ret < 0) {
110 bb_perror_nomsg_and_die();
111 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000112
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000113 if (!(opt & OPT_quiet)) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200114 const char *sep;
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000115 const char *name;
116
Mark Whitley6f932772001-03-20 19:18:10 +0000117 printf(
118 " mode: %d\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200119 "-o offset: %ld us\n"
120 "-f freq.adjust: %ld (65536 = 1ppm)\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000121 " maxerror: %ld\n"
122 " esterror: %ld\n"
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000123 " status: %d (",
Mark Whitley6f932772001-03-20 19:18:10 +0000124 txc.modes, txc.offset, txc.freq, txc.maxerror,
125 txc.esterror, txc.status);
126
127 /* representative output of next code fragment:
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200128 * "PLL | PPSTIME"
129 */
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000130 name = statlist_name;
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200131 sep = "";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000132 for (i = 0; statlist_bit[i]; i++) {
133 if (txc.status & statlist_bit[i]) {
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200134 printf("%s%s", sep, name);
135 sep = " | ";
Mark Whitley6f932772001-03-20 19:18:10 +0000136 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000137 name += strlen(name) + 1;
Mark Whitley6f932772001-03-20 19:18:10 +0000138 }
139
140 descript = "error";
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000141 if (ret <= 5)
142 descript = nth_string(ret_code_descript, ret);
143 printf(")\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000144 "-p timeconstant: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200145 " precision: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000146 " tolerance: %ld\n"
Denys Vlasenkoe152cb82014-04-17 11:29:34 +0200147 "-t tick: %ld us\n"
Mark Whitley6f932772001-03-20 19:18:10 +0000148 " time.tv_sec: %ld\n"
149 " time.tv_usec: %ld\n"
150 " return value: %d (%s)\n",
151 txc.constant,
152 txc.precision, txc.tolerance, txc.tick,
Eric Andersene76c3b02001-04-05 03:14:39 +0000153 (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript);
Mark Whitley6f932772001-03-20 19:18:10 +0000154 }
Denis Vlasenkobfc3d822007-11-04 04:10:17 +0000155
156 return 0;
Mark Whitley6f932772001-03-20 19:18:10 +0000157}