/contrib/ntp/util/tickadj.c
C | 902 lines | 773 code | 94 blank | 35 comment | 142 complexity | ee5f48cb18a7be54e1fcf1c57b01eb6a MD5 | raw file
- /*
- * tickadj - read, and possibly modify, the kernel `tick' and
- * `tickadj' variables, as well as `dosynctodr'. Note that
- * this operates on the running kernel only. I'd like to be
- * able to read and write the binary as well, but haven't
- * mastered this yet.
- *
- * HMS: The #includes here are different from those in xntpd/ntp_unixclock.c
- * These seem "worse".
- */
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- #include "ntp_types.h"
- #include "l_stdlib.h"
- #include <stdio.h>
- #ifdef HAVE_UNISTD_H
- # include <unistd.h>
- #endif /* HAVE_UNISTD_H */
- #ifdef HAVE___ADJTIMEX /* Linux */
- #include <sys/timex.h>
- struct timex txc;
- #if 0
- int
- main(
- int argc,
- char *argv[]
- )
- {
- int c, i;
- int quiet = 0;
- int errflg = 0;
- char *progname;
- extern int ntp_optind;
- extern char *ntp_optarg;
- progname = argv[0];
- if (argc==2 && argv[1][0] != '-') { /* old Linux format, for compatability */
- if ((i = atoi(argv[1])) > 0) {
- txc.time_tick = i;
- txc.modes = ADJ_TIMETICK;
- } else {
- fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
- errflg++;
- }
- } else {
- while ((c = ntp_getopt(argc, argv, "a:qt:")) != EOF) {
- switch (c) {
- case 'a':
- if ((i=atoi(ntp_optarg)) > 0) {
- txc.tickadj = i;
- txc.modes |= ADJ_TICKADJ;
- } else {
- (void) fprintf(stderr,
- "%s: unlikely value for tickadj: %s\n",
- progname, ntp_optarg);
- errflg++;
- }
- break;
- case 'q':
- quiet = 1;
- break;
- case 't':
- if ((i=atoi(ntp_optarg)) > 0) {
- txc.time_tick = i;
- txc.modes |= ADJ_TIMETICK;
- } else {
- (void) fprintf(stderr,
- "%s: unlikely value for tick: %s\n",
- progname, ntp_optarg);
- errflg++;
- }
- break;
- default:
- fprintf(stderr,
- "Usage: %s [tick_value]\n-or- %s [ -q ] [ -t tick ] [ -a tickadj ]\n",
- progname, progname);
- errflg++;
- break;
- }
- }
- }
- if (!errflg) {
- if (__adjtimex(&txc) < 0)
- perror("adjtimex");
- else if (!quiet)
- printf("tick = %ld\ntick_adj = %d\n",
- txc.time_tick, txc.tickadj);
- }
- exit(errflg ? 1 : 0);
- }
- #else
- int
- main(
- int argc,
- char *argv[]
- )
- {
- if (argc > 2)
- {
- fprintf(stderr, "Usage: %s [tick_value]\n", argv[0]);
- exit(-1);
- }
- else if (argc == 2)
- {
- #ifdef ADJ_TIMETICK
- if ( (txc.time_tick = atoi(argv[1])) < 1 )
- #else
- if ( (txc.tick = atoi(argv[1])) < 1 )
- #endif
- {
- fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
- exit(-1);
- }
- #ifdef ADJ_TIMETICK
- txc.modes = ADJ_TIMETICK;
- #else
- #ifdef MOD_OFFSET
- txc.modes = ADJ_TICK;
- #else
- txc.mode = ADJ_TICK;
- #endif
- #endif
- }
- else
- {
- #ifdef ADJ_TIMETICK
- txc.modes = 0;
- #else
- #ifdef MOD_OFFSET
- txc.modes = 0;
- #else
- txc.mode = 0;
- #endif
- #endif
- }
-
- if (__adjtimex(&txc) < 0)
- {
- perror("adjtimex");
- }
- else
- {
- #ifdef ADJ_TIMETICK
- printf("tick = %ld\ntick_adj = %ld\n", txc.time_tick, txc.tickadj);
- #else
- printf("tick = %ld\n", txc.tick);
- #endif
- }
- exit(0);
- }
- #endif
- #else /* not Linux... kmem tweaking: */
- #ifdef HAVE_SYS_FILE_H
- # include <sys/file.h>
- #endif
- #include <sys/stat.h>
- #ifdef HAVE_SYS_PARAM_H
- # include <sys/param.h>
- #endif
- #ifdef NLIST_STRUCT
- # include <nlist.h>
- #else /* not NLIST_STRUCT */ /* was defined(SYS_AUX3) || defined(SYS_AUX2) */
- # include <sys/resource.h>
- # include <sys/file.h>
- # include <a.out.h>
- # include <sys/var.h>
- #endif
- #include "ntp_io.h"
- #include "ntp_stdlib.h"
- #ifdef hz /* Was: RS6000 */
- # undef hz
- #endif /* hz */
- #ifdef HAVE_KVM_OPEN
- # include <kvm.h>
- #endif
- #ifdef SYS_VXWORKS
- /* vxWorks needs mode flag -casey*/
- #define open(name, flags) open(name, flags, 0777)
- #endif
- #ifndef L_SET /* Was: defined(SYS_PTX) || defined(SYS_IX86OSF1) */
- # define L_SET SEEK_SET
- #endif
- #ifndef HZ
- # define HZ DEFAULT_HZ
- #endif
- #define KMEM "/dev/kmem"
- #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
- char *progname;
- volatile int debug;
- int dokmem = 1;
- int writetickadj = 0;
- int writeopttickadj = 0;
- int unsetdosync = 0;
- int writetick = 0;
- int quiet = 0;
- int setnoprintf = 0;
- const char *kmem = KMEM;
- const char *file = NULL;
- int fd = -1;
- static void getoffsets P((off_t *, off_t *, off_t *, off_t *));
- static int openfile P((const char *, int));
- static void writevar P((int, off_t, int));
- static void readvar P((int, off_t, int *));
- /*
- * main - parse arguments and handle options
- */
- int
- main(
- int argc,
- char *argv[]
- )
- {
- int c;
- int errflg = 0;
- off_t tickadj_offset;
- off_t tick_offset;
- off_t dosync_offset;
- off_t noprintf_offset;
- int tickadj, ktickadj; /* HMS: Why isn't this u_long? */
- int tick, ktick; /* HMS: Why isn't this u_long? */
- int dosynctodr;
- int noprintf;
- int hz;
- int hz_int, hz_hundredths;
- int recommend_tickadj;
- long tmp;
- progname = argv[0];
- while ((c = ntp_getopt(argc, argv, "a:Adkpqst:")) != EOF)
- {
- switch (c)
- {
- case 'a':
- writetickadj = atoi(ntp_optarg);
- if (writetickadj <= 0)
- {
- (void) fprintf(stderr,
- "%s: unlikely value for tickadj: %s\n",
- progname, ntp_optarg);
- errflg++;
- }
- #if defined SCO5_CLOCK
- if (writetickadj % HZ)
- {
- writetickadj = (writetickadj / HZ) * HZ;
- (void) fprintf(stderr,
- "tickadj truncated to: %d\n", writetickadj);
- }
- #endif /* SCO5_CLOCK */
- break;
- case 'A':
- writeopttickadj = 1;
- break;
- case 'd':
- ++debug;
- break;
- case 'k':
- dokmem = 1;
- break;
- case 'p':
- setnoprintf = 1;
- break;
- case 'q':
- quiet = 1;
- break;
- case 's':
- unsetdosync = 1;
- break;
- case 't':
- writetick = atoi(ntp_optarg);
- if (writetick <= 0)
- {
- (void) fprintf(stderr,
- "%s: unlikely value for tick: %s\n",
- progname, ntp_optarg);
- errflg++;
- }
- break;
- default:
- errflg++;
- break;
- }
- }
- if (errflg || ntp_optind != argc)
- {
- (void) fprintf(stderr,
- "usage: %s [-Adkpqs] [-a newadj] [-t newtick]\n", progname);
- exit(2);
- }
- getoffsets(&tick_offset, &tickadj_offset, &dosync_offset, &noprintf_offset);
- if (debug)
- {
- (void) printf("tick offset = %lu\n", (unsigned long)tick_offset);
- (void) printf("tickadj offset = %lu\n", (unsigned long)tickadj_offset);
- (void) printf("dosynctodr offset = %lu\n", (unsigned long)dosync_offset);
- (void) printf("noprintf offset = %lu\n", (unsigned long)noprintf_offset);
- }
- if (writetick && (tick_offset == 0))
- {
- (void) fprintf(stderr,
- "No tick kernel variable\n");
- errflg++;
- }
-
- if (writeopttickadj && (tickadj_offset == 0))
- {
- (void) fprintf(stderr,
- "No tickadj kernel variable\n");
- errflg++;
- }
- if (unsetdosync && (dosync_offset == 0))
- {
- (void) fprintf(stderr,
- "No dosynctodr kernel variable\n");
- errflg++;
- }
-
- if (setnoprintf && (noprintf_offset == 0))
- {
- (void) fprintf(stderr,
- "No noprintf kernel variable\n");
- errflg++;
- }
- if (tick_offset != 0)
- {
- readvar(fd, tick_offset, &tick);
- #if defined(TICK_NANO) && defined(K_TICK_NAME)
- if (!quiet)
- (void) printf("KERNEL %s = %d nsec\n", K_TICK_NAME, tick);
- #endif /* TICK_NANO && K_TICK_NAME */
- #ifdef TICK_NANO
- tick /= 1000;
- #endif
- }
- else
- {
- tick = 0;
- }
- if (tickadj_offset != 0)
- {
- readvar(fd, tickadj_offset, &tickadj);
- #ifdef SCO5_CLOCK
- /* scale from nsec/sec to usec/tick */
- tickadj /= (1000L * HZ);
- #endif /*SCO5_CLOCK */
- #if defined(TICKADJ_NANO) && defined(K_TICKADJ_NAME)
- if (!quiet)
- (void) printf("KERNEL %s = %d nsec\n", K_TICKADJ_NAME, tickadj);
- #endif /* TICKADJ_NANO && K_TICKADJ_NAME */
- #ifdef TICKADJ_NANO
- tickadj += 999;
- tickadj /= 1000;
- #endif
- }
- else
- {
- tickadj = 0;
- }
- if (dosync_offset != 0)
- {
- readvar(fd, dosync_offset, &dosynctodr);
- }
- if (noprintf_offset != 0)
- {
- readvar(fd, noprintf_offset, &noprintf);
- }
- (void) close(fd);
- if (unsetdosync && dosync_offset == 0)
- {
- (void) fprintf(stderr,
- "%s: can't find %s in namelist\n",
- progname,
- #ifdef K_DOSYNCTODR_NAME
- K_DOSYNCTODR_NAME
- #else /* not K_DOSYNCTODR_NAME */
- "dosynctodr"
- #endif /* not K_DOSYNCTODR_NAME */
- );
- exit(1);
- }
- hz = HZ;
- #if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
- hz = (int) sysconf (_SC_CLK_TCK);
- #endif /* not HAVE_SYSCONF && _SC_CLK_TCK */
- #ifdef OVERRIDE_HZ
- hz = DEFAULT_HZ;
- #endif
- ktick = tick;
- #ifdef PRESET_TICK
- tick = PRESET_TICK;
- #endif /* PRESET_TICK */
- #ifdef TICKADJ_NANO
- tickadj /= 1000;
- if (tickadj == 0)
- tickadj = 1;
- #endif
- ktickadj = tickadj;
- #ifdef PRESET_TICKADJ
- tickadj = (PRESET_TICKADJ) ? PRESET_TICKADJ : 1;
- #endif /* PRESET_TICKADJ */
- if (!quiet)
- {
- if (tick_offset != 0)
- {
- (void) printf("KERNEL tick = %d usec (from %s kernel variable)\n",
- ktick,
- #ifdef K_TICK_NAME
- K_TICK_NAME
- #else
- "<this can't happen>"
- #endif
- );
- }
- #ifdef PRESET_TICK
- (void) printf("PRESET tick = %d usec\n", tick);
- #endif /* PRESET_TICK */
- if (tickadj_offset != 0)
- {
- (void) printf("KERNEL tickadj = %d usec (from %s kernel variable)\n",
- ktickadj,
- #ifdef K_TICKADJ_NAME
- K_TICKADJ_NAME
- #else
- "<this can't happen>"
- #endif
- );
- }
- #ifdef PRESET_TICKADJ
- (void) printf("PRESET tickadj = %d usec\n", tickadj);
- #endif /* PRESET_TICKADJ */
- if (dosync_offset != 0)
- {
- (void) printf("dosynctodr is %s\n", dosynctodr ? "on" : "off");
- }
- if (noprintf_offset != 0)
- {
- (void) printf("kernel level printf's: %s\n",
- noprintf ? "off" : "on");
- }
- }
- if (tick <= 0)
- {
- (void) fprintf(stderr, "%s: the value of tick is silly!\n",
- progname);
- exit(1);
- }
- hz_int = (int)(1000000L / (long)tick);
- hz_hundredths = (int)((100000000L / (long)tick) - ((long)hz_int * 100L));
- if (!quiet)
- {
- (void) printf("KERNEL hz = %d\n", hz);
- (void) printf("calculated hz = %d.%02d Hz\n", hz_int,
- hz_hundredths);
- }
- #if defined SCO5_CLOCK
- recommend_tickadj = 100;
- #else /* SCO5_CLOCK */
- tmp = (long) tick * 500L;
- recommend_tickadj = (int)(tmp / 1000000L);
- if (tmp % 1000000L > 0)
- {
- recommend_tickadj++;
- }
- #ifdef MIN_REC_TICKADJ
- if (recommend_tickadj < MIN_REC_TICKADJ)
- {
- recommend_tickadj = MIN_REC_TICKADJ;
- }
- #endif /* MIN_REC_TICKADJ */
- #endif /* SCO5_CLOCK */
-
- if ((!quiet) && (tickadj_offset != 0))
- {
- (void) printf("recommended value of tickadj = %d us\n",
- recommend_tickadj);
- }
- if ( writetickadj == 0
- && !writeopttickadj
- && !unsetdosync
- && writetick == 0
- && !setnoprintf)
- {
- exit(errflg ? 1 : 0);
- }
- if (writetickadj == 0 && writeopttickadj)
- {
- writetickadj = recommend_tickadj;
- }
- fd = openfile(file, O_WRONLY);
- if (setnoprintf && (noprintf_offset != 0))
- {
- if (!quiet)
- {
- (void) fprintf(stderr, "setting noprintf: ");
- (void) fflush(stderr);
- }
- writevar(fd, noprintf_offset, 1);
- if (!quiet)
- {
- (void) fprintf(stderr, "done!\n");
- }
- }
- if ((writetick > 0) && (tick_offset != 0))
- {
- if (!quiet)
- {
- (void) fprintf(stderr, "writing tick, value %d: ",
- writetick);
- (void) fflush(stderr);
- }
- writevar(fd, tick_offset, writetick);
- if (!quiet)
- {
- (void) fprintf(stderr, "done!\n");
- }
- }
- if ((writetickadj > 0) && (tickadj_offset != 0))
- {
- if (!quiet)
- {
- (void) fprintf(stderr, "writing tickadj, value %d: ",
- writetickadj);
- (void) fflush(stderr);
- }
- #ifdef SCO5_CLOCK
- /* scale from usec/tick to nsec/sec */
- writetickadj *= (1000L * HZ);
- #endif /* SCO5_CLOCK */
- writevar(fd, tickadj_offset, writetickadj);
- if (!quiet)
- {
- (void) fprintf(stderr, "done!\n");
- }
- }
- if (unsetdosync && (dosync_offset != 0))
- {
- if (!quiet)
- {
- (void) fprintf(stderr, "zeroing dosynctodr: ");
- (void) fflush(stderr);
- }
- writevar(fd, dosync_offset, 0);
- if (!quiet)
- {
- (void) fprintf(stderr, "done!\n");
- }
- }
- (void) close(fd);
- return(errflg ? 1 : 0);
- }
- /*
- * getoffsets - read the magic offsets from the specified file
- */
- static void
- getoffsets(
- off_t *tick_off,
- off_t *tickadj_off,
- off_t *dosync_off,
- off_t *noprintf_off
- )
- {
- #ifndef NOKMEM
- # ifndef HAVE_KVM_OPEN
- const char **kname;
- # endif
- #endif
- #ifndef NOKMEM
- # ifdef NLIST_NAME_UNION
- # define NL_B {{
- # define NL_E }}
- # else
- # define NL_B {
- # define NL_E }
- # endif
- #endif
- #define K_FILLER_NAME "DavidLetterman"
- #ifdef NLIST_EXTRA_INDIRECTION
- int i;
- #endif
- #ifndef NOKMEM
- static struct nlist nl[] =
- {
- NL_B
- #ifdef K_TICKADJ_NAME
- #define N_TICKADJ 0
- K_TICKADJ_NAME
- #else
- K_FILLER_NAME
- #endif
- NL_E,
- NL_B
- #ifdef K_TICK_NAME
- #define N_TICK 1
- K_TICK_NAME
- #else
- K_FILLER_NAME
- #endif
- NL_E,
- NL_B
- #ifdef K_DOSYNCTODR_NAME
- #define N_DOSYNC 2
- K_DOSYNCTODR_NAME
- #else
- K_FILLER_NAME
- #endif
- NL_E,
- NL_B
- #ifdef K_NOPRINTF_NAME
- #define N_NOPRINTF 3
- K_NOPRINTF_NAME
- #else
- K_FILLER_NAME
- #endif
- NL_E,
- NL_B "" NL_E,
- };
- #ifndef HAVE_KVM_OPEN
- static const char *kernels[] =
- {
- #ifdef HAVE_GETBOOTFILE
- NULL, /* *** SEE BELOW! *** */
- #endif
- "/kernel/unix",
- "/kernel",
- "/vmunix",
- "/unix",
- "/mach",
- "/hp-ux",
- "/386bsd",
- "/netbsd",
- "/stand/vmunix",
- "/bsd",
- NULL
- };
- #endif /* not HAVE_KVM_OPEN */
- #ifdef HAVE_KVM_OPEN
- /*
- * Solaris > 2.5 doesn't have a kernel file. Use the kvm_* interface
- * to read the kernel name list. -- stolcke 3/4/96
- */
- kvm_t *kvm_handle = kvm_open(NULL, NULL, NULL, O_RDONLY, progname);
- if (kvm_handle == NULL)
- {
- (void) fprintf(stderr,
- "%s: kvm_open failed\n",
- progname);
- exit(1);
- }
- if (kvm_nlist(kvm_handle, nl) == -1)
- {
- (void) fprintf(stderr,
- "%s: kvm_nlist failed\n",
- progname);
- exit(1);
- }
- kvm_close(kvm_handle);
- #else /* not HAVE_KVM_OPEN */
- #ifdef HAVE_GETBOOTFILE /* *** SEE HERE! *** */
- if (kernels[0] == NULL)
- {
- char * cp = (char *)getbootfile();
- if (cp)
- {
- kernels[0] = cp;
- }
- else
- {
- kernels[0] = "/Placeholder";
- }
- }
- #endif /* HAVE_GETBOOTFILE */
- for (kname = kernels; *kname != NULL; kname++)
- {
- struct stat stbuf;
- if (stat(*kname, &stbuf) == -1)
- {
- continue;
- }
- if (nlist(*kname, nl) >= 0)
- {
- break;
- }
- else
- {
- (void) fprintf(stderr,
- "%s: nlist didn't find needed symbols from <%s>: %s\n",
- progname, *kname, strerror(errno));
- }
- }
- if (*kname == NULL)
- {
- (void) fprintf(stderr,
- "%s: Couldn't find the kernel\n",
- progname);
- exit(1);
- }
- #endif /* HAVE_KVM_OPEN */
- if (dokmem)
- {
- file = kmem;
- fd = openfile(file, O_RDONLY);
- #ifdef NLIST_EXTRA_INDIRECTION
- /*
- * Go one more round of indirection.
- */
- for (i = 0; i < (sizeof(nl) / sizeof(struct nlist)); i++)
- {
- if ((nl[i].n_value) && (nl[i].n_sclass == 0x6b))
- {
- readvar(fd, nl[i].n_value, &nl[i].n_value);
- }
- }
- #endif /* NLIST_EXTRA_INDIRECTION */
- }
- #endif /* not NOKMEM */
- *tickadj_off = 0;
- *tick_off = 0;
- *dosync_off = 0;
- *noprintf_off = 0;
- #if defined(N_TICKADJ)
- *tickadj_off = nl[N_TICKADJ].n_value;
- #endif
- #if defined(N_TICK)
- *tick_off = nl[N_TICK].n_value;
- #endif
- #if defined(N_DOSYNC)
- *dosync_off = nl[N_DOSYNC].n_value;
- #endif
- #if defined(N_NOPRINTF)
- *noprintf_off = nl[N_NOPRINTF].n_value;
- #endif
- return;
- }
- #undef N_TICKADJ
- #undef N_TICK
- #undef N_DOSYNC
- #undef N_NOPRINTF
- /*
- * openfile - open the file, check for errors
- */
- static int
- openfile(
- const char *name,
- int mode
- )
- {
- int ifd;
- ifd = open(name, mode);
- if (ifd < 0)
- {
- (void) fprintf(stderr, "%s: open %s: ", progname, name);
- perror("");
- exit(1);
- }
- return ifd;
- }
- /*
- * writevar - write a variable into the file
- */
- static void
- writevar(
- int ofd,
- off_t off,
- int var
- )
- {
-
- if (lseek(ofd, off, L_SET) == -1)
- {
- (void) fprintf(stderr, "%s: lseek fails: ", progname);
- perror("");
- exit(1);
- }
- if (write(ofd, (char *)&var, sizeof(int)) != sizeof(int))
- {
- (void) fprintf(stderr, "%s: write fails: ", progname);
- perror("");
- exit(1);
- }
- return;
- }
- /*
- * readvar - read a variable from the file
- */
- static void
- readvar(
- int ifd,
- off_t off,
- int *var
- )
- {
- int i;
-
- if (lseek(ifd, off, L_SET) == -1)
- {
- (void) fprintf(stderr, "%s: lseek fails: ", progname);
- perror("");
- exit(1);
- }
- i = read(ifd, (char *)var, sizeof(int));
- if (i < 0)
- {
- (void) fprintf(stderr, "%s: read fails: ", progname);
- perror("");
- exit(1);
- }
- if (i != sizeof(int))
- {
- (void) fprintf(stderr, "%s: read expected %d, got %d\n",
- progname, (int)sizeof(int), i);
- exit(1);
- }
- return;
- }
- #endif /* not Linux */