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