98b6ccfbfe3dfdbd01ae84646f6607fb215de009
[oweals/busybox.git] / miscutils / adjtimex.c
1 /* vi: set sw=4 ts=4: */
2 /*
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  *
9  * busyboxed 20 March 2001, Larry Doolittle <ldoolitt@recycle.lbl.gov>
10  *
11  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
12  */
13
14 //usage:#define adjtimex_trivial_usage
15 //usage:       "[-q] [-o OFF] [-f FREQ] [-p TCONST] [-t TICK]"
16 //usage:#define adjtimex_full_usage "\n\n"
17 //usage:       "Read and optionally set system timebase parameters. See adjtimex(2)\n"
18 //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)"
21 //usage:     "\n                (positive values make clock run faster)"
22 //usage:     "\n        -t TICK Microseconds per tick, usually 10000"
23 //usage:     "\n        -p TCONST"
24
25 #include "libbb.h"
26 #include <sys/timex.h>
27
28 static const uint16_t statlist_bit[] = {
29         STA_PLL,
30         STA_PPSFREQ,
31         STA_PPSTIME,
32         STA_FLL,
33         STA_INS,
34         STA_DEL,
35         STA_UNSYNC,
36         STA_FREQHOLD,
37         STA_PPSSIGNAL,
38         STA_PPSJITTER,
39         STA_PPSWANDER,
40         STA_PPSERROR,
41         STA_CLOCKERR,
42         0
43 };
44 static const char statlist_name[] =
45         "PLL"       "\0"
46         "PPSFREQ"   "\0"
47         "PPSTIME"   "\0"
48         "FFL"       "\0"
49         "INS"       "\0"
50         "DEL"       "\0"
51         "UNSYNC"    "\0"
52         "FREQHOLD"  "\0"
53         "PPSSIGNAL" "\0"
54         "PPSJITTER" "\0"
55         "PPSWANDER" "\0"
56         "PPSERROR"  "\0"
57         "CLOCKERR"
58 ;
59
60 static const char ret_code_descript[] =
61         "clock synchronized" "\0"
62         "insert leap second" "\0"
63         "delete leap second" "\0"
64         "leap second in progress" "\0"
65         "leap second has occurred" "\0"
66         "clock not synchronized"
67 ;
68
69 int adjtimex_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
70 int adjtimex_main(int argc UNUSED_PARAM, char **argv)
71 {
72         enum {
73                 OPT_quiet = 0x1
74         };
75         unsigned opt;
76         char *opt_o, *opt_f, *opt_p, *opt_t;
77         struct timex txc;
78         int i, ret;
79         const char *descript;
80
81         opt_complementary = "=0"; /* no valid non-option parameters */
82         opt = getopt32(argv, "qo:f:p:t:",
83                         &opt_o, &opt_f, &opt_p, &opt_t);
84         txc.modes = 0;
85         //if (opt & 0x1) // -q
86         if (opt & 0x2) { // -o
87                 txc.offset = xatol(opt_o);
88                 txc.modes |= ADJ_OFFSET_SINGLESHOT;
89         }
90         if (opt & 0x4) { // -f
91                 txc.freq = xatol(opt_f);
92                 txc.modes |= ADJ_FREQUENCY;
93         }
94         if (opt & 0x8) { // -p
95                 txc.constant = xatol(opt_p);
96                 txc.modes |= ADJ_TIMECONST;
97         }
98         if (opt & 0x10) { // -t
99                 txc.tick = xatol(opt_t);
100                 txc.modes |= ADJ_TICK;
101         }
102
103         ret = adjtimex(&txc);
104
105         if (ret < 0) {
106                 bb_perror_nomsg_and_die();
107         }
108
109         if (!(opt & OPT_quiet)) {
110                 int sep;
111                 const char *name;
112
113                 printf(
114                         "    mode:         %d\n"
115                         "-o  offset:       %ld\n"
116                         "-f  frequency:    %ld\n"
117                         "    maxerror:     %ld\n"
118                         "    esterror:     %ld\n"
119                         "    status:       %d (",
120                 txc.modes, txc.offset, txc.freq, txc.maxerror,
121                 txc.esterror, txc.status);
122
123                 /* representative output of next code fragment:
124                    "PLL | PPSTIME" */
125                 name = statlist_name;
126                 sep = 0;
127                 for (i = 0; statlist_bit[i]; i++) {
128                         if (txc.status & statlist_bit[i]) {
129                                 if (sep)
130                                         fputs(" | ", stdout);
131                                 fputs(name, stdout);
132                                 sep = 1;
133                         }
134                         name += strlen(name) + 1;
135                 }
136
137                 descript = "error";
138                 if (ret <= 5)
139                         descript = nth_string(ret_code_descript, ret);
140                 printf(")\n"
141                         "-p  timeconstant: %ld\n"
142                         "    precision:    %ld\n"
143                         "    tolerance:    %ld\n"
144                         "-t  tick:         %ld\n"
145                         "    time.tv_sec:  %ld\n"
146                         "    time.tv_usec: %ld\n"
147                         "    return value: %d (%s)\n",
148                 txc.constant,
149                 txc.precision, txc.tolerance, txc.tick,
150                 (long)txc.time.tv_sec, (long)txc.time.tv_usec, ret, descript);
151         }
152
153         return 0;
154 }