busybox/miscutils/adjtimex.c
<<
>>
Prefs
   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//config:config ADJTIMEX
  14//config:       bool "adjtimex (4.7 kb)"
  15//config:       default y
  16//config:       help
  17//config:       Adjtimex reads and optionally sets adjustment parameters for
  18//config:       the Linux clock adjustment algorithm.
  19
  20//applet:IF_ADJTIMEX(APPLET_NOFORK(adjtimex, adjtimex, BB_DIR_SBIN, BB_SUID_DROP, adjtimex))
  21
  22//kbuild:lib-$(CONFIG_ADJTIMEX) += adjtimex.o
  23
  24//usage:#define adjtimex_trivial_usage
  25//usage:       "[-q] [-o OFS] [-f FREQ] [-p TCONST] [-t TICK]"
  26//usage:#define adjtimex_full_usage "\n\n"
  27//usage:       "Read or set kernel time variables. See adjtimex(2)\n"
  28//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)"
  31//usage:     "\n        -t TICK Microseconds per tick, usually 10000"
  32//usage:     "\n                (positive -t or -f values make clock run faster)"
  33//usage:     "\n        -p TCONST"
  34
  35#include "libbb.h"
  36#ifdef __BIONIC__
  37# include <linux/timex.h>
  38#else
  39# include <sys/timex.h>
  40#endif
  41
  42static const uint16_t statlist_bit[] ALIGN2 = {
  43        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
  57};
  58static const char statlist_name[] ALIGN1 =
  59        "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;
  73
  74static const char ret_code_descript[] ALIGN1 =
  75        "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"
  80        "clock not synchronized"
  81;
  82
  83int adjtimex_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  84int adjtimex_main(int argc UNUSED_PARAM, char **argv)
  85{
  86        enum {
  87                OPT_quiet = 0x1
  88        };
  89        unsigned opt;
  90        char *opt_o, *opt_f, *opt_p, *opt_t;
  91        struct timex txc;
  92        int ret;
  93        const char *descript;
  94
  95        memset(&txc, 0, sizeof(txc));
  96
  97        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        );
 101        //if (opt & 0x1) // -q
 102        if (opt & 0x2) { // -o
 103                txc.offset = xatol(opt_o);
 104                txc.modes |= ADJ_OFFSET_SINGLESHOT;
 105        }
 106        if (opt & 0x4) { // -f
 107                txc.freq = xatol(opt_f);
 108                txc.modes |= ADJ_FREQUENCY;
 109        }
 110        if (opt & 0x8) { // -p
 111                txc.constant = xatol(opt_p);
 112                txc.modes |= ADJ_TIMECONST;
 113        }
 114        if (opt & 0x10) { // -t
 115                txc.tick = xatol(opt_t);
 116                txc.modes |= ADJ_TICK;
 117        }
 118
 119        /* 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
 124        ret = adjtimex(&txc);
 125        if (ret < 0)
 126                bb_perror_nomsg_and_die();
 127
 128        if (!(opt & OPT_quiet)) {
 129                const char *sep;
 130                const char *name;
 131                int i;
 132
 133                printf(
 134                        "    mode:         %d\n"
 135                        "-o  offset:       %ld us\n"
 136                        "-f  freq.adjust:  %ld (65536 = 1ppm)\n"
 137                        "    maxerror:     %ld\n"
 138                        "    esterror:     %ld\n"
 139                        "    status:       %d (",
 140                        txc.modes, txc.offset, txc.freq, txc.maxerror,
 141                        txc.esterror, txc.status
 142                );
 143
 144                /* representative output of next code fragment:
 145                 * "PLL | PPSTIME"
 146                 */
 147                name = statlist_name;
 148                sep = "";
 149                for (i = 0; statlist_bit[i]; i++) {
 150                        if (txc.status & statlist_bit[i]) {
 151                                printf("%s%s", sep, name);
 152                                sep = " | ";
 153                        }
 154                        name += strlen(name) + 1;
 155                }
 156
 157                descript = "error";
 158                if (ret <= 5)
 159                        descript = nth_string(ret_code_descript, ret);
 160                printf(")\n"
 161                        "-p  timeconstant: %ld\n"
 162                        "    precision:    %ld us\n"
 163                        "    tolerance:    %ld\n"
 164                        "-t  tick:         %ld us\n"
 165                        "    time.tv_sec:  %ld\n"
 166                        "    time.tv_usec: %ld\n"
 167                        "    return value: %d (%s)\n",
 168                        txc.constant,
 169                        txc.precision, txc.tolerance, txc.tick,
 170                        (long)txc.time.tv_sec, (long)txc.time.tv_usec,
 171                        ret, descript
 172                );
 173        }
 174
 175        return 0;
 176}
 177