4 * tickadj - read, and possibly modify, the kernel `tick' and
5 * `tickadj' variables, as well as `dosynctodr'. Note that
6 * this operates on the running kernel only. I'd like to be
7 * able to read and write the binary as well, but haven't
10 * HMS: The #includes here are different from those in xntpd/ntp_unixclock.c
18 #include "ntp_types.h"
24 #endif /* HAVE_UNISTD_H */
26 #ifdef HAVE___ADJTIMEX /* Linux */
28 #include <sys/timex.h>
42 extern int ntp_optind
;
43 extern char *ntp_optarg
;
46 if (argc
==2 && argv
[1][0] != '-') { /* old Linux format, for compatability */
47 if ((i
= atoi(argv
[1])) > 0) {
49 txc
.modes
= ADJ_TIMETICK
;
51 fprintf(stderr
, "Silly value for tick: %s\n", argv
[1]);
55 while ((c
= ntp_getopt(argc
, argv
, "a:qt:")) != EOF
) {
58 if ((i
=atoi(ntp_optarg
)) > 0) {
60 txc
.modes
|= ADJ_TICKADJ
;
62 (void) fprintf(stderr
,
63 "%s: unlikely value for tickadj: %s\n",
64 progname
, ntp_optarg
);
74 if ((i
=atoi(ntp_optarg
)) > 0) {
76 txc
.modes
|= ADJ_TIMETICK
;
78 (void) fprintf(stderr
,
79 "%s: unlikely value for tick: %s\n",
80 progname
, ntp_optarg
);
87 "Usage: %s [tick_value]\n-or- %s [ -q ] [ -t tick ] [ -a tickadj ]\n",
96 if (__adjtimex(&txc
) < 0)
99 printf("tick = %ld\ntick_adj = %d\n",
100 txc
.time_tick
, txc
.tickadj
);
103 exit(errflg
? 1 : 0);
114 fprintf(stderr
, "Usage: %s [tick_value]\n", argv
[0]);
120 if ( (txc
.time_tick
= atoi(argv
[1])) < 1 )
122 if ( (txc
.tick
= atoi(argv
[1])) < 1 )
125 fprintf(stderr
, "Silly value for tick: %s\n", argv
[1]);
129 txc
.modes
= ADJ_TIMETICK
;
132 txc
.modes
= ADJ_TICK
;
151 if (__adjtimex(&txc
) < 0)
158 printf("tick = %ld\ntick_adj = %ld\n", txc
.time_tick
, txc
.tickadj
);
160 printf("tick = %ld\n", txc
.tick
);
168 #else /* not Linux... kmem tweaking: */
170 #ifdef HAVE_SYS_FILE_H
171 # include <sys/file.h>
173 #include <sys/stat.h>
175 #ifdef HAVE_SYS_PARAM_H
176 # include <sys/param.h>
181 #else /* not NLIST_STRUCT */ /* was defined(SYS_AUX3) || defined(SYS_AUX2) */
182 # include <sys/resource.h>
183 # include <sys/file.h>
185 # include <sys/var.h>
189 #include "ntp_stdlib.h"
191 #ifdef hz /* Was: RS6000 */
200 /* vxWorks needs mode flag -casey*/
201 #define open(name, flags) open(name, flags, 0777)
204 #ifndef L_SET /* Was: defined(SYS_PTX) || defined(SYS_IX86OSF1) */
205 # define L_SET SEEK_SET
209 # define HZ DEFAULT_HZ
212 #define KMEM "/dev/kmem"
213 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
219 int writetickadj
= 0;
220 int writeopttickadj
= 0;
226 const char *kmem
= KMEM
;
227 const char *file
= NULL
;
230 static void getoffsets
P((off_t
*, off_t
*, off_t
*, off_t
*));
231 static int openfile
P((const char *, int));
232 static void writevar
P((int, off_t
, int));
233 static void readvar
P((int, off_t
, int *));
236 * main - parse arguments and handle options
246 off_t tickadj_offset
;
249 off_t noprintf_offset
;
250 int tickadj
, ktickadj
; /* HMS: Why isn't this u_long? */
251 int tick
, ktick
; /* HMS: Why isn't this u_long? */
255 int hz_int
, hz_hundredths
;
256 int recommend_tickadj
;
260 while ((c
= ntp_getopt(argc
, argv
, "a:Adkpqst:")) != EOF
)
265 writetickadj
= atoi(ntp_optarg
);
266 if (writetickadj
<= 0)
268 (void) fprintf(stderr
,
269 "%s: unlikely value for tickadj: %s\n",
270 progname
, ntp_optarg
);
274 #if defined SCO5_CLOCK
275 if (writetickadj
% HZ
)
277 writetickadj
= (writetickadj
/ HZ
) * HZ
;
278 (void) fprintf(stderr
,
279 "tickadj truncated to: %d\n", writetickadj
);
281 #endif /* SCO5_CLOCK */
303 writetick
= atoi(ntp_optarg
);
306 (void) fprintf(stderr
,
307 "%s: unlikely value for tick: %s\n",
308 progname
, ntp_optarg
);
317 if (errflg
|| ntp_optind
!= argc
)
319 (void) fprintf(stderr
,
320 "usage: %s [-Adkpqs] [-a newadj] [-t newtick]\n", progname
);
324 getoffsets(&tick_offset
, &tickadj_offset
, &dosync_offset
, &noprintf_offset
);
328 (void) printf("tick offset = %lu\n", (unsigned long)tick_offset
);
329 (void) printf("tickadj offset = %lu\n", (unsigned long)tickadj_offset
);
330 (void) printf("dosynctodr offset = %lu\n", (unsigned long)dosync_offset
);
331 (void) printf("noprintf offset = %lu\n", (unsigned long)noprintf_offset
);
334 if (writetick
&& (tick_offset
== 0))
336 (void) fprintf(stderr
,
337 "No tick kernel variable\n");
341 if (writeopttickadj
&& (tickadj_offset
== 0))
343 (void) fprintf(stderr
,
344 "No tickadj kernel variable\n");
348 if (unsetdosync
&& (dosync_offset
== 0))
350 (void) fprintf(stderr
,
351 "No dosynctodr kernel variable\n");
355 if (setnoprintf
&& (noprintf_offset
== 0))
357 (void) fprintf(stderr
,
358 "No noprintf kernel variable\n");
362 if (tick_offset
!= 0)
364 readvar(fd
, tick_offset
, &tick
);
365 #if defined(TICK_NANO) && defined(K_TICK_NAME)
367 (void) printf("KERNEL %s = %d nsec\n", K_TICK_NAME
, tick
);
368 #endif /* TICK_NANO && K_TICK_NAME */
379 if (tickadj_offset
!= 0)
381 readvar(fd
, tickadj_offset
, &tickadj
);
384 /* scale from nsec/sec to usec/tick */
385 tickadj
/= (1000L * HZ
);
386 #endif /*SCO5_CLOCK */
388 #if defined(TICKADJ_NANO) && defined(K_TICKADJ_NAME)
390 (void) printf("KERNEL %s = %d nsec\n", K_TICKADJ_NAME
, tickadj
);
391 #endif /* TICKADJ_NANO && K_TICKADJ_NAME */
403 if (dosync_offset
!= 0)
405 readvar(fd
, dosync_offset
, &dosynctodr
);
408 if (noprintf_offset
!= 0)
410 readvar(fd
, noprintf_offset
, &noprintf
);
415 if (unsetdosync
&& dosync_offset
== 0)
417 (void) fprintf(stderr
,
418 "%s: can't find %s in namelist\n",
420 #ifdef K_DOSYNCTODR_NAME
422 #else /* not K_DOSYNCTODR_NAME */
424 #endif /* not K_DOSYNCTODR_NAME */
430 #if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
431 hz
= (int) sysconf (_SC_CLK_TCK
);
432 #endif /* not HAVE_SYSCONF && _SC_CLK_TCK */
439 #endif /* PRESET_TICK */
446 #ifdef PRESET_TICKADJ
447 tickadj
= (PRESET_TICKADJ
) ? PRESET_TICKADJ
: 1;
448 #endif /* PRESET_TICKADJ */
452 if (tick_offset
!= 0)
454 (void) printf("KERNEL tick = %d usec (from %s kernel variable)\n",
459 "<this can't happen>"
464 (void) printf("PRESET tick = %d usec\n", tick
);
465 #endif /* PRESET_TICK */
466 if (tickadj_offset
!= 0)
468 (void) printf("KERNEL tickadj = %d usec (from %s kernel variable)\n",
470 #ifdef K_TICKADJ_NAME
473 "<this can't happen>"
477 #ifdef PRESET_TICKADJ
478 (void) printf("PRESET tickadj = %d usec\n", tickadj
);
479 #endif /* PRESET_TICKADJ */
480 if (dosync_offset
!= 0)
482 (void) printf("dosynctodr is %s\n", dosynctodr
? "on" : "off");
484 if (noprintf_offset
!= 0)
486 (void) printf("kernel level printf's: %s\n",
487 noprintf
? "off" : "on");
493 (void) fprintf(stderr
, "%s: the value of tick is silly!\n",
498 hz_int
= (int)(1000000L / (long)tick
);
499 hz_hundredths
= (int)((100000000L / (long)tick
) - ((long)hz_int
* 100L));
502 (void) printf("KERNEL hz = %d\n", hz
);
503 (void) printf("calculated hz = %d.%02d Hz\n", hz_int
,
507 #if defined SCO5_CLOCK
508 recommend_tickadj
= 100;
509 #else /* SCO5_CLOCK */
510 tmp
= (long) tick
* 500L;
511 recommend_tickadj
= (int)(tmp
/ 1000000L);
512 if (tmp
% 1000000L > 0)
517 #ifdef MIN_REC_TICKADJ
518 if (recommend_tickadj
< MIN_REC_TICKADJ
)
520 recommend_tickadj
= MIN_REC_TICKADJ
;
522 #endif /* MIN_REC_TICKADJ */
523 #endif /* SCO5_CLOCK */
526 if ((!quiet
) && (tickadj_offset
!= 0))
528 (void) printf("recommended value of tickadj = %d us\n",
532 if ( writetickadj
== 0
538 exit(errflg
? 1 : 0);
541 if (writetickadj
== 0 && writeopttickadj
)
543 writetickadj
= recommend_tickadj
;
546 fd
= openfile(file
, O_WRONLY
);
548 if (setnoprintf
&& (noprintf_offset
!= 0))
552 (void) fprintf(stderr
, "setting noprintf: ");
553 (void) fflush(stderr
);
555 writevar(fd
, noprintf_offset
, 1);
558 (void) fprintf(stderr
, "done!\n");
562 if ((writetick
> 0) && (tick_offset
!= 0))
566 (void) fprintf(stderr
, "writing tick, value %d: ",
568 (void) fflush(stderr
);
570 writevar(fd
, tick_offset
, writetick
);
573 (void) fprintf(stderr
, "done!\n");
577 if ((writetickadj
> 0) && (tickadj_offset
!= 0))
581 (void) fprintf(stderr
, "writing tickadj, value %d: ",
583 (void) fflush(stderr
);
587 /* scale from usec/tick to nsec/sec */
588 writetickadj
*= (1000L * HZ
);
589 #endif /* SCO5_CLOCK */
591 writevar(fd
, tickadj_offset
, writetickadj
);
594 (void) fprintf(stderr
, "done!\n");
598 if (unsetdosync
&& (dosync_offset
!= 0))
602 (void) fprintf(stderr
, "zeroing dosynctodr: ");
603 (void) fflush(stderr
);
605 writevar(fd
, dosync_offset
, 0);
608 (void) fprintf(stderr
, "done!\n");
612 return(errflg
? 1 : 0);
616 * getoffsets - read the magic offsets from the specified file
628 # ifndef HAVE_KVM_OPEN
634 # ifdef NLIST_NAME_UNION
643 #define K_FILLER_NAME "DavidLetterman"
645 #ifdef NLIST_EXTRA_INDIRECTION
650 static struct nlist nl
[] =
653 #ifdef K_TICKADJ_NAME
669 #ifdef K_DOSYNCTODR_NAME
677 #ifdef K_NOPRINTF_NAME
687 #ifndef HAVE_KVM_OPEN
688 static const char *kernels
[] =
690 #ifdef HAVE_GETBOOTFILE
691 NULL
, /* *** SEE BELOW! *** */
705 #endif /* not HAVE_KVM_OPEN */
709 * Solaris > 2.5 doesn't have a kernel file. Use the kvm_* interface
710 * to read the kernel name list. -- stolcke 3/4/96
712 kvm_t
*kvm_handle
= kvm_open(NULL
, NULL
, NULL
, O_RDONLY
, progname
);
714 if (kvm_handle
== NULL
)
716 (void) fprintf(stderr
,
717 "%s: kvm_open failed\n",
721 if (kvm_nlist(kvm_handle
, nl
) == -1)
723 (void) fprintf(stderr
,
724 "%s: kvm_nlist failed\n",
728 kvm_close(kvm_handle
);
729 #else /* not HAVE_KVM_OPEN */
730 #ifdef HAVE_GETBOOTFILE /* *** SEE HERE! *** */
731 if (kernels
[0] == NULL
)
733 char * cp
= (char *)getbootfile();
741 kernels
[0] = "/Placeholder";
744 #endif /* HAVE_GETBOOTFILE */
745 for (kname
= kernels
; *kname
!= NULL
; kname
++)
749 if (stat(*kname
, &stbuf
) == -1)
753 if (nlist(*kname
, nl
) >= 0)
759 (void) fprintf(stderr
,
760 "%s: nlist didn't find needed symbols from <%s>: %s\n",
761 progname
, *kname
, strerror(errno
));
766 (void) fprintf(stderr
,
767 "%s: Couldn't find the kernel\n",
771 #endif /* HAVE_KVM_OPEN */
777 fd
= openfile(file
, O_RDONLY
);
778 #ifdef NLIST_EXTRA_INDIRECTION
780 * Go one more round of indirection.
782 for (i
= 0; i
< (sizeof(nl
) / sizeof(struct nlist
)); i
++)
784 if ((nl
[i
].n_value
) && (nl
[i
].n_sclass
== 0x6b))
786 readvar(fd
, nl
[i
].n_value
, &nl
[i
].n_value
);
789 #endif /* NLIST_EXTRA_INDIRECTION */
791 #endif /* not NOKMEM */
798 #if defined(N_TICKADJ)
799 *tickadj_off
= nl
[N_TICKADJ
].n_value
;
803 *tick_off
= nl
[N_TICK
].n_value
;
806 #if defined(N_DOSYNC)
807 *dosync_off
= nl
[N_DOSYNC
].n_value
;
810 #if defined(N_NOPRINTF)
811 *noprintf_off
= nl
[N_NOPRINTF
].n_value
;
823 * openfile - open the file, check for errors
833 ifd
= open(name
, mode
);
836 (void) fprintf(stderr
, "%s: open %s: ", progname
, name
);
845 * writevar - write a variable into the file
855 if (lseek(ofd
, off
, L_SET
) == -1)
857 (void) fprintf(stderr
, "%s: lseek fails: ", progname
);
861 if (write(ofd
, (char *)&var
, sizeof(int)) != sizeof(int))
863 (void) fprintf(stderr
, "%s: write fails: ", progname
);
872 * readvar - read a variable from the file
883 if (lseek(ifd
, off
, L_SET
) == -1)
885 (void) fprintf(stderr
, "%s: lseek fails: ", progname
);
889 i
= read(ifd
, (char *)var
, sizeof(int));
892 (void) fprintf(stderr
, "%s: read fails: ", progname
);
896 if (i
!= sizeof(int))
898 (void) fprintf(stderr
, "%s: read expected %d, got %d\n",
899 progname
, (int)sizeof(int), i
);
904 #endif /* not Linux */