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