Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / util / tickadj.c
blobe1bba1d842cc03b903daa0de7d15ee8e7325f559
1 /* $NetBSD$ */
3 /*
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
8 * mastered this yet.
10 * HMS: The #includes here are different from those in xntpd/ntp_unixclock.c
11 * These seem "worse".
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #include "ntp_types.h"
19 #include "l_stdlib.h"
21 #include <stdio.h>
22 #ifdef HAVE_UNISTD_H
23 # include <unistd.h>
24 #endif /* HAVE_UNISTD_H */
26 #ifdef HAVE___ADJTIMEX /* Linux */
28 #include <sys/timex.h>
29 struct timex txc;
31 #if 0
32 int
33 main(
34 int argc,
35 char *argv[]
38 int c, i;
39 int quiet = 0;
40 int errflg = 0;
41 char *progname;
42 extern int ntp_optind;
43 extern char *ntp_optarg;
45 progname = argv[0];
46 if (argc==2 && argv[1][0] != '-') { /* old Linux format, for compatability */
47 if ((i = atoi(argv[1])) > 0) {
48 txc.time_tick = i;
49 txc.modes = ADJ_TIMETICK;
50 } else {
51 fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
52 errflg++;
54 } else {
55 while ((c = ntp_getopt(argc, argv, "a:qt:")) != EOF) {
56 switch (c) {
57 case 'a':
58 if ((i=atoi(ntp_optarg)) > 0) {
59 txc.tickadj = i;
60 txc.modes |= ADJ_TICKADJ;
61 } else {
62 (void) fprintf(stderr,
63 "%s: unlikely value for tickadj: %s\n",
64 progname, ntp_optarg);
65 errflg++;
67 break;
69 case 'q':
70 quiet = 1;
71 break;
73 case 't':
74 if ((i=atoi(ntp_optarg)) > 0) {
75 txc.time_tick = i;
76 txc.modes |= ADJ_TIMETICK;
77 } else {
78 (void) fprintf(stderr,
79 "%s: unlikely value for tick: %s\n",
80 progname, ntp_optarg);
81 errflg++;
83 break;
85 default:
86 fprintf(stderr,
87 "Usage: %s [tick_value]\n-or- %s [ -q ] [ -t tick ] [ -a tickadj ]\n",
88 progname, progname);
89 errflg++;
90 break;
95 if (!errflg) {
96 if (__adjtimex(&txc) < 0)
97 perror("adjtimex");
98 else if (!quiet)
99 printf("tick = %ld\ntick_adj = %d\n",
100 txc.time_tick, txc.tickadj);
103 exit(errflg ? 1 : 0);
105 #else
107 main(
108 int argc,
109 char *argv[]
112 if (argc > 2)
114 fprintf(stderr, "Usage: %s [tick_value]\n", argv[0]);
115 exit(-1);
117 else if (argc == 2)
119 #ifdef ADJ_TIMETICK
120 if ( (txc.time_tick = atoi(argv[1])) < 1 )
121 #else
122 if ( (txc.tick = atoi(argv[1])) < 1 )
123 #endif
125 fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
126 exit(-1);
128 #ifdef ADJ_TIMETICK
129 txc.modes = ADJ_TIMETICK;
130 #else
131 #ifdef MOD_OFFSET
132 txc.modes = ADJ_TICK;
133 #else
134 txc.mode = ADJ_TICK;
135 #endif
136 #endif
138 else
140 #ifdef ADJ_TIMETICK
141 txc.modes = 0;
142 #else
143 #ifdef MOD_OFFSET
144 txc.modes = 0;
145 #else
146 txc.mode = 0;
147 #endif
148 #endif
151 if (__adjtimex(&txc) < 0)
153 perror("adjtimex");
155 else
157 #ifdef ADJ_TIMETICK
158 printf("tick = %ld\ntick_adj = %ld\n", txc.time_tick, txc.tickadj);
159 #else
160 printf("tick = %ld\n", txc.tick);
161 #endif
164 exit(0);
166 #endif
168 #else /* not Linux... kmem tweaking: */
170 #ifdef HAVE_SYS_FILE_H
171 # include <sys/file.h>
172 #endif
173 #include <sys/stat.h>
175 #ifdef HAVE_SYS_PARAM_H
176 # include <sys/param.h>
177 #endif
179 #ifdef NLIST_STRUCT
180 # include <nlist.h>
181 #else /* not NLIST_STRUCT */ /* was defined(SYS_AUX3) || defined(SYS_AUX2) */
182 # include <sys/resource.h>
183 # include <sys/file.h>
184 # include <a.out.h>
185 # include <sys/var.h>
186 #endif
188 #include "ntp_io.h"
189 #include "ntp_stdlib.h"
191 #ifdef hz /* Was: RS6000 */
192 # undef hz
193 #endif /* hz */
195 #ifdef HAVE_KVM_OPEN
196 # include <kvm.h>
197 #endif
199 #ifdef SYS_VXWORKS
200 /* vxWorks needs mode flag -casey*/
201 #define open(name, flags) open(name, flags, 0777)
202 #endif
204 #ifndef L_SET /* Was: defined(SYS_PTX) || defined(SYS_IX86OSF1) */
205 # define L_SET SEEK_SET
206 #endif
208 #ifndef HZ
209 # define HZ DEFAULT_HZ
210 #endif
212 #define KMEM "/dev/kmem"
213 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
215 char *progname;
216 volatile int debug;
218 int dokmem = 1;
219 int writetickadj = 0;
220 int writeopttickadj = 0;
221 int unsetdosync = 0;
222 int writetick = 0;
223 int quiet = 0;
224 int setnoprintf = 0;
226 const char *kmem = KMEM;
227 const char *file = NULL;
228 int fd = -1;
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
239 main(
240 int argc,
241 char *argv[]
244 int c;
245 int errflg = 0;
246 off_t tickadj_offset;
247 off_t tick_offset;
248 off_t dosync_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? */
252 int dosynctodr;
253 int noprintf;
254 int hz;
255 int hz_int, hz_hundredths;
256 int recommend_tickadj;
257 long tmp;
259 progname = argv[0];
260 while ((c = ntp_getopt(argc, argv, "a:Adkpqst:")) != EOF)
262 switch (c)
264 case 'a':
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);
271 errflg++;
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 */
283 break;
284 case 'A':
285 writeopttickadj = 1;
286 break;
287 case 'd':
288 ++debug;
289 break;
290 case 'k':
291 dokmem = 1;
292 break;
293 case 'p':
294 setnoprintf = 1;
295 break;
296 case 'q':
297 quiet = 1;
298 break;
299 case 's':
300 unsetdosync = 1;
301 break;
302 case 't':
303 writetick = atoi(ntp_optarg);
304 if (writetick <= 0)
306 (void) fprintf(stderr,
307 "%s: unlikely value for tick: %s\n",
308 progname, ntp_optarg);
309 errflg++;
311 break;
312 default:
313 errflg++;
314 break;
317 if (errflg || ntp_optind != argc)
319 (void) fprintf(stderr,
320 "usage: %s [-Adkpqs] [-a newadj] [-t newtick]\n", progname);
321 exit(2);
324 getoffsets(&tick_offset, &tickadj_offset, &dosync_offset, &noprintf_offset);
326 if (debug)
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");
338 errflg++;
341 if (writeopttickadj && (tickadj_offset == 0))
343 (void) fprintf(stderr,
344 "No tickadj kernel variable\n");
345 errflg++;
348 if (unsetdosync && (dosync_offset == 0))
350 (void) fprintf(stderr,
351 "No dosynctodr kernel variable\n");
352 errflg++;
355 if (setnoprintf && (noprintf_offset == 0))
357 (void) fprintf(stderr,
358 "No noprintf kernel variable\n");
359 errflg++;
362 if (tick_offset != 0)
364 readvar(fd, tick_offset, &tick);
365 #if defined(TICK_NANO) && defined(K_TICK_NAME)
366 if (!quiet)
367 (void) printf("KERNEL %s = %d nsec\n", K_TICK_NAME, tick);
368 #endif /* TICK_NANO && K_TICK_NAME */
370 #ifdef TICK_NANO
371 tick /= 1000;
372 #endif
374 else
376 tick = 0;
379 if (tickadj_offset != 0)
381 readvar(fd, tickadj_offset, &tickadj);
383 #ifdef SCO5_CLOCK
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)
389 if (!quiet)
390 (void) printf("KERNEL %s = %d nsec\n", K_TICKADJ_NAME, tickadj);
391 #endif /* TICKADJ_NANO && K_TICKADJ_NAME */
393 #ifdef TICKADJ_NANO
394 tickadj += 999;
395 tickadj /= 1000;
396 #endif
398 else
400 tickadj = 0;
403 if (dosync_offset != 0)
405 readvar(fd, dosync_offset, &dosynctodr);
408 if (noprintf_offset != 0)
410 readvar(fd, noprintf_offset, &noprintf);
413 (void) close(fd);
415 if (unsetdosync && dosync_offset == 0)
417 (void) fprintf(stderr,
418 "%s: can't find %s in namelist\n",
419 progname,
420 #ifdef K_DOSYNCTODR_NAME
421 K_DOSYNCTODR_NAME
422 #else /* not K_DOSYNCTODR_NAME */
423 "dosynctodr"
424 #endif /* not K_DOSYNCTODR_NAME */
426 exit(1);
429 hz = HZ;
430 #if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
431 hz = (int) sysconf (_SC_CLK_TCK);
432 #endif /* not HAVE_SYSCONF && _SC_CLK_TCK */
433 #ifdef OVERRIDE_HZ
434 hz = DEFAULT_HZ;
435 #endif
436 ktick = tick;
437 #ifdef PRESET_TICK
438 tick = PRESET_TICK;
439 #endif /* PRESET_TICK */
440 #ifdef TICKADJ_NANO
441 tickadj /= 1000;
442 if (tickadj == 0)
443 tickadj = 1;
444 #endif
445 ktickadj = tickadj;
446 #ifdef PRESET_TICKADJ
447 tickadj = (PRESET_TICKADJ) ? PRESET_TICKADJ : 1;
448 #endif /* PRESET_TICKADJ */
450 if (!quiet)
452 if (tick_offset != 0)
454 (void) printf("KERNEL tick = %d usec (from %s kernel variable)\n",
455 ktick,
456 #ifdef K_TICK_NAME
457 K_TICK_NAME
458 #else
459 "<this can't happen>"
460 #endif
463 #ifdef PRESET_TICK
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",
469 ktickadj,
470 #ifdef K_TICKADJ_NAME
471 K_TICKADJ_NAME
472 #else
473 "<this can't happen>"
474 #endif
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");
491 if (tick <= 0)
493 (void) fprintf(stderr, "%s: the value of tick is silly!\n",
494 progname);
495 exit(1);
498 hz_int = (int)(1000000L / (long)tick);
499 hz_hundredths = (int)((100000000L / (long)tick) - ((long)hz_int * 100L));
500 if (!quiet)
502 (void) printf("KERNEL hz = %d\n", hz);
503 (void) printf("calculated hz = %d.%02d Hz\n", hz_int,
504 hz_hundredths);
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)
514 recommend_tickadj++;
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",
529 recommend_tickadj);
532 if ( writetickadj == 0
533 && !writeopttickadj
534 && !unsetdosync
535 && writetick == 0
536 && !setnoprintf)
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))
550 if (!quiet)
552 (void) fprintf(stderr, "setting noprintf: ");
553 (void) fflush(stderr);
555 writevar(fd, noprintf_offset, 1);
556 if (!quiet)
558 (void) fprintf(stderr, "done!\n");
562 if ((writetick > 0) && (tick_offset != 0))
564 if (!quiet)
566 (void) fprintf(stderr, "writing tick, value %d: ",
567 writetick);
568 (void) fflush(stderr);
570 writevar(fd, tick_offset, writetick);
571 if (!quiet)
573 (void) fprintf(stderr, "done!\n");
577 if ((writetickadj > 0) && (tickadj_offset != 0))
579 if (!quiet)
581 (void) fprintf(stderr, "writing tickadj, value %d: ",
582 writetickadj);
583 (void) fflush(stderr);
586 #ifdef SCO5_CLOCK
587 /* scale from usec/tick to nsec/sec */
588 writetickadj *= (1000L * HZ);
589 #endif /* SCO5_CLOCK */
591 writevar(fd, tickadj_offset, writetickadj);
592 if (!quiet)
594 (void) fprintf(stderr, "done!\n");
598 if (unsetdosync && (dosync_offset != 0))
600 if (!quiet)
602 (void) fprintf(stderr, "zeroing dosynctodr: ");
603 (void) fflush(stderr);
605 writevar(fd, dosync_offset, 0);
606 if (!quiet)
608 (void) fprintf(stderr, "done!\n");
611 (void) close(fd);
612 return(errflg ? 1 : 0);
616 * getoffsets - read the magic offsets from the specified file
618 static void
619 getoffsets(
620 off_t *tick_off,
621 off_t *tickadj_off,
622 off_t *dosync_off,
623 off_t *noprintf_off
627 #ifndef NOKMEM
628 # ifndef HAVE_KVM_OPEN
629 const char **kname;
630 # endif
631 #endif
633 #ifndef NOKMEM
634 # ifdef NLIST_NAME_UNION
635 # define NL_B {{
636 # define NL_E }}
637 # else
638 # define NL_B {
639 # define NL_E }
640 # endif
641 #endif
643 #define K_FILLER_NAME "DavidLetterman"
645 #ifdef NLIST_EXTRA_INDIRECTION
646 int i;
647 #endif
649 #ifndef NOKMEM
650 static struct nlist nl[] =
652 NL_B
653 #ifdef K_TICKADJ_NAME
654 #define N_TICKADJ 0
655 K_TICKADJ_NAME
656 #else
657 K_FILLER_NAME
658 #endif
659 NL_E,
660 NL_B
661 #ifdef K_TICK_NAME
662 #define N_TICK 1
663 K_TICK_NAME
664 #else
665 K_FILLER_NAME
666 #endif
667 NL_E,
668 NL_B
669 #ifdef K_DOSYNCTODR_NAME
670 #define N_DOSYNC 2
671 K_DOSYNCTODR_NAME
672 #else
673 K_FILLER_NAME
674 #endif
675 NL_E,
676 NL_B
677 #ifdef K_NOPRINTF_NAME
678 #define N_NOPRINTF 3
679 K_NOPRINTF_NAME
680 #else
681 K_FILLER_NAME
682 #endif
683 NL_E,
684 NL_B "" NL_E,
687 #ifndef HAVE_KVM_OPEN
688 static const char *kernels[] =
690 #ifdef HAVE_GETBOOTFILE
691 NULL, /* *** SEE BELOW! *** */
692 #endif
693 "/kernel/unix",
694 "/kernel",
695 "/vmunix",
696 "/unix",
697 "/mach",
698 "/hp-ux",
699 "/386bsd",
700 "/netbsd",
701 "/stand/vmunix",
702 "/bsd",
703 NULL
705 #endif /* not HAVE_KVM_OPEN */
707 #ifdef 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",
718 progname);
719 exit(1);
721 if (kvm_nlist(kvm_handle, nl) == -1)
723 (void) fprintf(stderr,
724 "%s: kvm_nlist failed\n",
725 progname);
726 exit(1);
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();
735 if (cp)
737 kernels[0] = cp;
739 else
741 kernels[0] = "/Placeholder";
744 #endif /* HAVE_GETBOOTFILE */
745 for (kname = kernels; *kname != NULL; kname++)
747 struct stat stbuf;
749 if (stat(*kname, &stbuf) == -1)
751 continue;
753 if (nlist(*kname, nl) >= 0)
755 break;
757 else
759 (void) fprintf(stderr,
760 "%s: nlist didn't find needed symbols from <%s>: %s\n",
761 progname, *kname, strerror(errno));
764 if (*kname == NULL)
766 (void) fprintf(stderr,
767 "%s: Couldn't find the kernel\n",
768 progname);
769 exit(1);
771 #endif /* HAVE_KVM_OPEN */
773 if (dokmem)
775 file = kmem;
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 */
793 *tickadj_off = 0;
794 *tick_off = 0;
795 *dosync_off = 0;
796 *noprintf_off = 0;
798 #if defined(N_TICKADJ)
799 *tickadj_off = nl[N_TICKADJ].n_value;
800 #endif
802 #if defined(N_TICK)
803 *tick_off = nl[N_TICK].n_value;
804 #endif
806 #if defined(N_DOSYNC)
807 *dosync_off = nl[N_DOSYNC].n_value;
808 #endif
810 #if defined(N_NOPRINTF)
811 *noprintf_off = nl[N_NOPRINTF].n_value;
812 #endif
813 return;
816 #undef N_TICKADJ
817 #undef N_TICK
818 #undef N_DOSYNC
819 #undef N_NOPRINTF
823 * openfile - open the file, check for errors
825 static int
826 openfile(
827 const char *name,
828 int mode
831 int ifd;
833 ifd = open(name, mode);
834 if (ifd < 0)
836 (void) fprintf(stderr, "%s: open %s: ", progname, name);
837 perror("");
838 exit(1);
840 return ifd;
845 * writevar - write a variable into the file
847 static void
848 writevar(
849 int ofd,
850 off_t off,
851 int var
855 if (lseek(ofd, off, L_SET) == -1)
857 (void) fprintf(stderr, "%s: lseek fails: ", progname);
858 perror("");
859 exit(1);
861 if (write(ofd, (char *)&var, sizeof(int)) != sizeof(int))
863 (void) fprintf(stderr, "%s: write fails: ", progname);
864 perror("");
865 exit(1);
867 return;
872 * readvar - read a variable from the file
874 static void
875 readvar(
876 int ifd,
877 off_t off,
878 int *var
881 int i;
883 if (lseek(ifd, off, L_SET) == -1)
885 (void) fprintf(stderr, "%s: lseek fails: ", progname);
886 perror("");
887 exit(1);
889 i = read(ifd, (char *)var, sizeof(int));
890 if (i < 0)
892 (void) fprintf(stderr, "%s: read fails: ", progname);
893 perror("");
894 exit(1);
896 if (i != sizeof(int))
898 (void) fprintf(stderr, "%s: read expected %d, got %d\n",
899 progname, (int)sizeof(int), i);
900 exit(1);
902 return;
904 #endif /* not Linux */