static int parse_double(char *s, double *d) { if (get_ranged_double(s, d, INT_MIN, INT_MAX) != PARSED_OK) return 1; return 0; }
static int do_set(clockid_t clkid, int cmdc, char *cmdv[]) { struct timespec ts; double time_arg = 0; int args_to_eat = 0; enum parser_result r; memset(&ts, 0, sizeof(ts)); /* if we have no more arguments, or the next argument is the ";" * separator, then we run set as default parameter mode */ if (cmdc < 1 || name_is_a_command(cmdv[0])) { clock_gettime(CLOCK_REALTIME, &ts); /* since we aren't using the options, we can simply ensure * that we don't eat any arguments */ args_to_eat = 0; } else { /* parse the double */ r = get_ranged_double(cmdv[0], &time_arg, 0.0, DBL_MAX); switch (r) { case PARSED_OK: break; case MALFORMED: pr_err("set: '%s' is not a valid double", cmdv[0]); return -2; case OUT_OF_RANGE: pr_err("set: '%s' is out of range", cmdv[0]); return -2; default: pr_err("set: couldn't process '%s'", cmdv[0]); return -2; } double_to_timespec(time_arg, &ts); /* in order for processing to work, we need to ensure the * run_cmds loop eats the optional set argument */ args_to_eat = 1; } if (clock_settime(clkid, &ts)) { pr_err("set: failed to set clock time: %s", strerror(errno)); return -1; } else { pr_notice("set clock time to %ld.%09ld or %s", ts.tv_sec, ts.tv_nsec, ctime(&ts.tv_sec)); } return args_to_eat; }
static int do_wait(clockid_t clkid, int cmdc, char *cmdv[]) { double time_arg; struct timespec ts; struct itimerval timer; enum parser_result r; if (cmdc < 1 || name_is_a_command(cmdv[0])) { pr_err("wait: requires sleep duration argument\n"); return -2; } memset(&timer, 0, sizeof(timer)); /* parse the double time offset argument */ r = get_ranged_double(cmdv[0], &time_arg, 0.0, DBL_MAX); switch (r) { case PARSED_OK: break; case MALFORMED: pr_err("wait: '%s' is not a valid double", cmdv[0]); return -2; case OUT_OF_RANGE: pr_err("wait: '%s' is out of range.", cmdv[0]); return -2; default: pr_err("wait: couldn't process '%s'", cmdv[0]); return -2; } double_to_timespec(time_arg, &ts); timer.it_value.tv_sec = ts.tv_sec; timer.it_value.tv_usec = ts.tv_nsec / 1000; setitimer(ITIMER_REAL, &timer, NULL); pause(); /* the SIGALRM is already trapped during initialization, so we will * wake up here once the alarm is handled. */ pr_notice( "process slept for %lf seconds\n", time_arg); return 1; }
static int do_freq(clockid_t clkid, int cmdc, char *cmdv[]) { double ppb; enum parser_result r; clockadj_init(clkid); if (cmdc < 1 || name_is_a_command(cmdv[0])) { ppb = clockadj_get_freq(clkid); pr_err("clock frequency offset is %lfppb", ppb); /* no argument was used */ return 0; } /* parse the double ppb argument */ r = get_ranged_double(cmdv[0], &ppb, -NSEC2SEC, NSEC2SEC); switch (r) { case PARSED_OK: break; case MALFORMED: pr_err("freq: '%s' is not a valid double", cmdv[0]); return -2; case OUT_OF_RANGE: pr_err("freq: '%s' is out of range.", cmdv[0]); return -2; default: pr_err("freq: couldn't process '%s'", cmdv[0]); return -2; } clockadj_set_freq(clkid, ppb); pr_err("adjusted clock frequency offset to %lfppb", ppb); /* consumed one argument to determine the frequency adjustment value */ return 1; }
static int do_adj(clockid_t clkid, int cmdc, char *cmdv[]) { double time_arg; int64_t nsecs; enum parser_result r; if (cmdc < 1 || name_is_a_command(cmdv[0])) { pr_err("adj: missing required time argument"); return -2; } /* parse the double time offset argument */ r = get_ranged_double(cmdv[0], &time_arg, DBL_MIN, DBL_MAX); switch (r) { case PARSED_OK: break; case MALFORMED: pr_err("adj: '%s' is not a valid double", cmdv[0]); return -2; case OUT_OF_RANGE: pr_err("adj: '%s' is out of range.", cmdv[0]); return -2; default: pr_err("adj: couldn't process '%s'", cmdv[0]); return -2; } nsecs = (int64_t)(NSEC2SEC * time_arg); clockadj_init(clkid); clockadj_step(clkid, nsecs); pr_notice("adjusted clock by %lf seconds", time_arg); /* adjustment always consumes one argument */ return 1; }