source: trunk/third/xntp/util/tickadj.c @ 10832

Revision 10832, 15.3 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * tickadj - read, and possibly modify, the kernel `tick' and
3 *           `tickadj' variables, as well as `dosynctodr'.  Note that
4 *           this operates on the running kernel only.  I'd like to be
5 *           able to read and write the binary as well, but haven't
6 *           mastered this yet.
7 *
8 * HMS: The #includes here are different from those in xntpd/ntp_unixclock.c
9 *      These seem "worse".
10 */
11
12#ifdef HAVE_CONFIG_H
13# include <config.h>
14#endif
15
16#include <stdio.h>
17#include <sys/types.h>
18#ifdef HAVE_UNISTD_H
19# include <unistd.h>
20#endif /* HAVE_UNISTD_H */
21
22#include "l_stdlib.h"
23
24#ifdef HAVE___ADJTIMEX          /* Linux */
25#include <sys/timex.h>
26
27struct timex txc;
28
29int
30main(int argc, char ** argv)
31{
32  if (argc > 2)
33    {
34      fprintf(stderr, "Usage: %s [tick_value]\n", argv[0]);
35      exit(-1);
36    }
37  else if (argc == 2)
38    {
39      if ( (txc.tick = atoi(argv[1])) < 1 )
40        {
41          fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
42          exit(-1);
43        }
44#ifdef MOD_OFFSET
45      txc.modes = ADJ_TICK;
46#else
47      txc.mode = ADJ_TICK;
48#endif
49    }
50  else
51    {
52#ifdef MOD_OFFSET
53      txc.modes = 0;
54#else
55      txc.mode = 0;
56#endif
57    }
58   
59  if (__adjtimex(&txc) < 0)
60    {
61      perror("adjtimex");
62    }
63  else
64    {
65      printf("tick = %ld\n", txc.tick);
66    }
67
68  return(0);
69}
70#else /* not Linux... kmem tweaking: */
71
72#ifdef HAVE_SYS_FILE_H
73# include <sys/file.h>
74#endif
75#include <sys/stat.h>
76
77#ifdef HAVE_SYS_PARAM_H
78# include <sys/param.h>
79#endif
80
81#ifdef NLIST_STRUCT
82# include <nlist.h>
83#else /* not NLIST_STRUCT */ /* was defined(SYS_AUX3) || defined(SYS_AUX2) */
84# include <sys/time.h>
85# include <sys/resource.h>
86# include <sys/file.h>
87# include <a.out.h>
88# include <sys/var.h>
89#endif
90
91#include "ntp_io.h"
92#include "ntp_stdlib.h"
93
94#ifdef hz /* Was: RS6000 */
95# undef hz
96#endif /* hz */
97
98#ifdef HAVE_LIBKVM
99# include <kvm.h>
100#endif
101
102#ifdef SYS_VXWORKS
103/* vxWorks needs mode flag -casey*/
104#define open(name, flags)   open(name, flags, 0777)
105#endif
106
107#ifndef L_SET   /* Was: defined(SYS_PTX) || defined(SYS_IX86OSF1) */
108# define L_SET SEEK_SET
109#endif
110
111#ifndef HZ
112# define HZ     DEFAULT_HZ
113#endif
114
115#define KMEM    "/dev/kmem"
116#define STREQ(a, b)     (*(a) == *(b) && strcmp((a), (b)) == 0)
117
118char *progname;
119int debug;
120
121int dokmem = 1;
122int writetickadj = 0;
123int writeopttickadj = 0;
124int unsetdosync = 0;
125int writetick = 0;
126int quiet = 0;
127int setnoprintf = 0;
128
129const char *kmem = KMEM;
130const char *file = NULL;
131int   fd  = -1;
132
133static  void    getoffsets      P((unsigned long *, unsigned long *, unsigned long *, unsigned long *));
134static  int     openfile        P((char *, int));
135static  void    writevar        P((int, unsigned long, int));
136static  void    readvar         P((int, unsigned long, int *));
137
138/*
139 * main - parse arguments and handle options
140 */
141void
142main(argc, argv)
143     int argc;
144     char *argv[];
145{
146  int c;
147  int errflg = 0;
148  extern int ntp_optind;
149  extern char *ntp_optarg;
150  unsigned long tickadj_offset;
151  unsigned long tick_offset;
152  unsigned long dosync_offset;
153  unsigned long noprintf_offset;
154  int tickadj, ktickadj;        /* HMS: Why isn't this u_long? */
155  int tick, ktick;              /* HMS: Why isn't this u_long? */
156  int dosynctodr;
157  int noprintf;
158  int hz;
159  int hz_int, hz_hundredths;
160  int recommend_tickadj;
161  long tmp;
162
163  progname = argv[0];
164  while ((c = ntp_getopt(argc, argv, "a:Adkpqst:")) != EOF)
165    {
166      switch (c)
167        {
168        case 'a':
169          writetickadj = atoi(ntp_optarg);
170          if (writetickadj <= 0)
171            {
172              (void) fprintf(stderr,
173                             "%s: unlikely value for tickadj: %s\n",
174                             progname, ntp_optarg);
175              errflg++;
176            }
177
178#if defined(SCO3_TICKADJ) || defined(SCO5_TICKADJ)
179          if (writetickadj % HZ)
180            {
181              writetickadj = (writetickadj / HZ) * HZ;
182              (void) fprintf(stderr,
183                             "tickadj truncated to: %d\n", writetickadj);
184            }
185#endif /* SCO3_TICKADJ || SCO5_TICKADJ */
186
187          break;
188        case 'A':
189          writeopttickadj = 1;
190          break;
191        case 'd':
192          ++debug;
193          break;
194        case 'k':
195          dokmem = 1;
196          break;
197        case 'p':
198          setnoprintf = 1;
199          break;
200        case 'q':
201          quiet = 1;
202          break;
203        case 's':
204          unsetdosync = 1;
205          break;
206        case 't':
207          writetick = atoi(ntp_optarg);
208          if (writetick <= 0)
209            {
210              (void) fprintf(stderr,
211                             "%s: unlikely value for tick: %s\n",
212                             progname, ntp_optarg);
213              errflg++;
214            }
215          break;
216        default:
217          errflg++;
218          break;
219        }
220    }
221  if (errflg || ntp_optind != argc)
222    {
223      (void) fprintf(stderr,
224                     "usage: %s [-Adkpqs] [-a newadj] [-t newtick]\n", progname);
225      exit(2);
226    }
227
228  getoffsets(&tick_offset, &tickadj_offset, &dosync_offset, &noprintf_offset);
229
230  if (debug)
231    {
232      (void) printf("tick offset = %lu\n", tick_offset);
233      (void) printf("tickadj offset = %lu\n", tickadj_offset);
234      (void) printf("dosynctodr offset = %lu\n", dosync_offset);
235      (void) printf("noprintf offset = %lu\n", noprintf_offset);
236    }
237
238  if (writetick && (tick_offset == 0))
239    {
240      (void) fprintf(stderr,
241                     "No tick kernel variable\n");
242      errflg++;
243    }
244       
245  if (writeopttickadj && (tickadj_offset == 0))
246    {
247      (void) fprintf(stderr,
248                     "No tickadj kernel variable\n");
249      errflg++;
250    }
251
252  if (unsetdosync && (dosync_offset == 0))
253    {
254      (void) fprintf(stderr,
255                     "No dosynctodr kernel variable\n");
256      errflg++;
257    }
258       
259  if (setnoprintf && (noprintf_offset == 0))
260    {
261      (void) fprintf(stderr,
262                     "No noprintf kernel variable\n");
263      errflg++;
264    }
265
266  if (tick_offset != 0)
267    {
268      readvar(fd, tick_offset, &tick);
269#if defined(TICK_NANO) && defined(K_TICK_NAME)
270      if (!quiet)
271        (void) printf("KERNEL %s = %d nsec\n", K_TICK_NAME, tick);
272#endif /* TICK_NANO && K_TICK_NAME */
273
274#ifdef TICK_NANO
275      tick /= 1000;
276#endif
277    }
278  else
279    {
280      tick = 0;
281    }
282
283  if (tickadj_offset != 0)
284    {
285      readvar(fd, tickadj_offset, &tickadj);
286
287#ifdef SCO3_TICKADJ
288      /* scale from ticks/sec to usec/tick */
289      tickadj *= (10000L / HZ);
290#endif /* SCO3_TICKADJ */
291#ifdef SCO5_TICKADJ
292      /* scale from nsec/sec to usec/tick */
293      tickadj /= (1000L * HZ);
294#endif /*SCO5_TICKADJ */
295
296#if defined(TICKADJ_NANO) && defined(K_TICKADJ_NAME)
297      if (!quiet)
298        (void) printf("KERNEL %s = %d nsec\n", K_TICKADJ_NAME, tickadj);
299#endif /* TICKADJ_NANO && K_TICKADJ_NAME */
300
301#ifdef TICKADJ_NANO
302      tickadj += 999;
303      tickadj /= 1000;
304#endif
305    }
306  else
307    {
308      tickadj = 0;
309    }
310
311  if (dosync_offset != 0)
312    {
313      readvar(fd, dosync_offset, &dosynctodr);
314    }
315
316  if (noprintf_offset != 0)
317    {
318      readvar(fd, noprintf_offset, &noprintf);
319    }
320
321  (void) close(fd);
322
323  if (unsetdosync && dosync_offset == 0)
324    {
325      (void) fprintf(stderr,
326                     "%s: can't find %s in namelist\n",
327                     progname,
328#ifdef K_DOSYNCTODR_NAME
329                     K_DOSYNCTODR_NAME
330#else /* not K_DOSYNCTODR_NAME */
331                     "dosynctodr"
332#endif /* not K_DOSYNCTODR_NAME */
333                     );
334      exit(1);
335    }
336
337  hz = HZ;
338#if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
339  hz = (int) sysconf (_SC_CLK_TCK);
340#endif /* not HAVE_SYSCONF && _SC_CLK_TCK */
341#ifdef OVERRIDE_HZ
342  hz = DEFAULT_HZ;
343#endif
344  ktick = tick;
345#ifdef PRESET_TICK
346  tick = PRESET_TICK;
347#endif /* PRESET_TICK */
348#ifdef TICKADJ_NANO
349   tickadj /= 1000;
350   if (tickadj == 0)
351     tickadj = 1;
352#endif
353  ktickadj = tickadj;
354#ifdef PRESET_TICKADJ
355  tickadj = (PRESET_TICKADJ) ? PRESET_TICKADJ : 1;
356#endif /* PRESET_TICKADJ */
357
358  if (!quiet)
359    {
360      if (tick_offset != 0)
361        {
362          (void) printf("KERNEL tick = %d usec (from %s kernel variable)\n",
363                        ktick,
364#ifdef K_TICK_NAME
365                        K_TICK_NAME
366#else
367                        "<this can't happen>"
368#endif                 
369                        );
370        }
371#ifdef PRESET_TICK
372      (void) printf("PRESET tick = %d usec\n", tick);
373#endif /* PRESET_TICK */
374      if (tickadj_offset != 0)
375        {
376          (void) printf("KERNEL tickadj = %d usec (from %s kernel variable)\n",
377                        ktickadj,
378#ifdef K_TICKADJ_NAME
379                        K_TICKADJ_NAME
380#else
381                        "<this can't happen>"
382#endif
383                        );
384        }
385#ifdef PRESET_TICKADJ
386      (void) printf("PRESET tickadj = %d usec\n", tickadj);
387#endif /* PRESET_TICKADJ */
388      if (dosync_offset != 0)
389        {
390          (void) printf("dosynctodr is %s\n", dosynctodr ? "on" : "off");
391        }
392      if (noprintf_offset != 0)
393        {
394          (void) printf("kernel level printf's: %s\n",
395                        noprintf ? "off" : "on");
396        }
397    }
398
399  if (tick <= 0)
400    {
401      (void) fprintf(stderr, "%s: the value of tick is silly!\n",
402                     progname);
403      exit(1);
404    }
405
406  hz_int = (int)(1000000L / (long)tick);
407  hz_hundredths = (int)((100000000L / (long)tick) - ((long)hz_int * 100L));
408  if (!quiet)
409    {
410      (void) printf("KERNEL hz = %d\n", hz);
411      (void) printf("calculated hz = %d.%02d Hz\n", hz_int,
412                    hz_hundredths);
413    }
414
415#if defined(SCO3_TICKADJ) || defined(SCO5_TICKADJ)
416  recommend_tickadj = 100;
417#else /* SCO3_TICKADJ */
418  tmp = (long) tick * 500L;
419  recommend_tickadj = (int)(tmp / 1000000L);
420  if (tmp % 1000000L > 0)
421    {
422      recommend_tickadj++;
423    }
424
425#ifdef MIN_REC_TICKADJ
426  if (recommend_tickadj < MIN_REC_TICKADJ)
427    {
428      recommend_tickadj = MIN_REC_TICKADJ;
429    }
430#endif /* MIN_REC_TICKADJ */
431#endif /* SCO3_TICKADJ */
432 
433
434  if ((!quiet) && (tickadj_offset != 0))
435    {
436      (void) printf("recommended value of tickadj = %d us\n",
437                    recommend_tickadj);
438    }
439
440  if (   writetickadj == 0
441      && !writeopttickadj
442      && !unsetdosync
443      && writetick == 0
444      && !setnoprintf)
445    {
446      exit(errflg ? 1 : 0);
447    }
448
449  if (writetickadj == 0 && writeopttickadj)
450    {
451      writetickadj = recommend_tickadj;
452    }
453
454  fd = openfile(file, O_WRONLY);
455
456  if (setnoprintf && (dosync_offset != 0))
457    {
458      if (!quiet)
459        {
460          (void) fprintf(stderr, "setting noprintf: ");
461          (void) fflush(stderr);
462        }
463      writevar(fd, noprintf_offset, 1);
464      if (!quiet)
465        {
466          (void) fprintf(stderr, "done!\n");
467        }
468    }
469
470  if ((writetick > 0) && (tick_offset != 0))
471    {
472      if (!quiet)
473        {
474          (void) fprintf(stderr, "writing tick, value %d: ",
475                         writetick);
476          (void) fflush(stderr);
477        }
478      writevar(fd, tick_offset, writetick);
479      if (!quiet)
480        {
481          (void) fprintf(stderr, "done!\n");
482        }
483    }
484
485  if ((writetickadj > 0) && (tickadj_offset != 0))
486    {
487      if (!quiet)
488        {
489          (void) fprintf(stderr, "writing tickadj, value %d: ",
490                         writetickadj);
491          (void) fflush(stderr);
492        }
493
494#ifdef SCO3_TICKADJ
495      /* scale from usec/tick to ticks/sec */
496      writetickadj /= (10000L / HZ);
497#endif /* SCO3_TICKADJ */
498#ifdef SCO5_TICKADJ
499      /* scale from usec/tick to nsec/sec */
500      writetickadj *= (1000L * HZ);
501#endif /* SCO5_TICKADJ */
502
503      writevar(fd, tickadj_offset, writetickadj);
504      if (!quiet)
505        {
506          (void) fprintf(stderr, "done!\n");
507        }
508    }
509
510  if (unsetdosync && (dosync_offset != 0))
511    {
512      if (!quiet)
513        {
514          (void) fprintf(stderr, "zeroing dosynctodr: ");
515          (void) fflush(stderr);
516        }
517      writevar(fd, dosync_offset, 0);
518      if (!quiet)
519        {
520          (void) fprintf(stderr, "done!\n");
521        }
522    }
523  (void) close(fd);
524  exit(errflg ? 1 : 0);
525}
526
527/*
528 * getoffsets - read the magic offsets from the specified file
529 */
530static void
531getoffsets(tick_off, tickadj_off, dosync_off, noprintf_off)
532     unsigned long *tick_off;
533     unsigned long *tickadj_off;
534     unsigned long *dosync_off;
535     unsigned long *noprintf_off;
536{
537  char **kname;
538
539#ifndef NOKMEM
540# ifdef NLIST_NAME_UNION
541#  define NL_B {{
542#  define NL_E }}
543# else
544#  define NL_B {
545#  define NL_E }
546# endif
547#endif
548
549#define K_FILLER_NAME "DavidLetterman"
550
551#ifdef NLIST_EXTRA_INDIRECTION
552  int i;
553#endif
554
555#ifndef NOKMEM
556  static struct nlist nl[] =
557  {
558    NL_B
559#ifdef K_TICKADJ_NAME
560#define N_TICKADJ       0
561    K_TICKADJ_NAME
562#else
563    K_FILLER_NAME
564#endif
565    NL_E,
566    NL_B
567#ifdef K_TICK_NAME
568#define N_TICK          1
569    K_TICK_NAME
570#else
571    K_FILLER_NAME
572#endif
573    NL_E,
574    NL_B
575#ifdef K_DOSYNCTODR_NAME
576#define N_DOSYNC        2
577    K_DOSYNCTODR_NAME
578#else
579    K_FILLER_NAME
580#endif
581    NL_E,
582    NL_B
583#ifdef K_NOPRINTF_NAME
584#define N_NOPRINTF      3
585    K_NOPRINTF_NAME
586#else
587    K_FILLER_NAME
588#endif
589    NL_E,
590    NL_B "" NL_E,
591  };
592
593  static const char *kernels[] =
594  {
595#ifdef HAVE_GETBOOTFILE
596    NULL,                       /* *** SEE BELOW! *** */
597#endif
598    "/kernel/unix",
599    "/kernel",
600    "/vmunix",
601    "/unix",
602    "/mach",
603    "hp-ux",
604    "/386bsd",
605    "/netbsd",
606    "/stand/vmunix",
607    "/bsd",
608    NULL
609  };
610
611#ifdef HAVE_KVM_OPEN
612  /*
613   * Solaris > 2.5 doesn't have a kernel file.  Use the kvm_* interface
614   * to read the kernel name list. -- stolcke 3/4/96
615   */
616  kvm_t *kvm_handle = kvm_open(NULL, NULL, NULL, O_RDONLY, progname);
617
618  if (kvm_handle == NULL)
619    {
620      (void) fprintf(stderr,
621                     "%s: kvm_open failed\n",
622                     progname);
623      exit(1);
624    }
625  if (kvm_nlist(kvm_handle, nl) == -1)
626    {
627      (void) fprintf(stderr,
628                     "%s: kvm_nlist failed\n",
629                     progname);
630      exit(1);
631    }
632  kvm_close(kvm_handle);
633  kname = &kernels[0];  /* dummy */
634#else /* not HAVE_KVM_OPEN */
635#ifdef HAVE_GETBOOTFILE         /* *** SEE HERE! *** */
636  if (kernels[0] == NULL)
637    {
638      char * cp = (char *)getbootfile();
639
640      if (cp)
641        {
642          kernels[0] = cp;
643        }
644    else
645      {
646        kernels[0] = "/Placeholder";
647      }
648    }
649#endif /* HAVE_GETBOOTFILE */
650  for (kname = kernels; *kname != NULL; kname++)
651    {
652      struct stat stbuf;
653
654      if (stat(*kname, &stbuf) == -1)
655        {
656          continue;
657        }
658      if (nlist(*kname, nl) >= 0)
659        {
660          break;
661        }
662      else
663        {
664          (void) fprintf(stderr,
665                         "%s: nlist didn't find needed symbols from <%s>: %m\n",
666                         progname, *kname);
667        }
668    }
669  if (*kname == NULL)
670    {
671      (void) fprintf(stderr,
672                     "%s: Couldn't find the kernel\n",
673                     progname);
674      exit(1);
675    }
676#endif /* HAVE_KVM_OPEN */
677
678  if (dokmem)
679    {
680      file = kmem;
681
682      fd = openfile(file, O_RDONLY);
683#ifdef NLIST_EXTRA_INDIRECTION
684      /*
685       * Go one more round of indirection.
686       */
687      for (i = 0; i < (sizeof(nl) / sizeof(struct nlist)); i++)
688        {
689          if ((nl[i].n_value) && (nl[i].n_sclass == 0x6b))
690            {
691              readvar(fd, nl[i].n_value, &nl[i].n_value);
692            }
693        }
694#endif /* NLIST_EXTRA_INDIRECTION */
695    }
696#endif /* not NOKMEM */
697
698  *tickadj_off  = 0;
699  *tick_off     = 0;
700  *dosync_off   = 0;
701  *noprintf_off = 0;
702
703#if defined(N_TICKADJ)
704  *tickadj_off = nl[N_TICKADJ].n_value;
705#endif
706
707#if defined(N_TICK)
708  *tick_off = nl[N_TICK].n_value;
709#endif
710
711#if defined(N_DOSYNC)
712  *dosync_off = nl[N_DOSYNC].n_value;
713#endif
714
715#if defined(N_NOPRINTF)
716  *noprintf_off = nl[N_NOPRINTF].n_value;
717#endif
718  return;
719}
720
721#undef N_TICKADJ
722#undef N_TICK
723#undef N_DOSYNC
724#undef N_NOPRINTF
725
726
727/*
728 * openfile - open the file, check for errors
729 */
730static int
731openfile(name, mode)
732     char *name;
733     int mode;
734{
735  int fd;
736
737  fd = open(name, mode);
738  if (fd < 0)
739    {
740      (void) fprintf(stderr, "%s: open %s: ", progname, name);
741      perror("");
742      exit(1);
743    }
744  return fd;
745}
746
747
748/*
749 * writevar - write a variable into the file
750 */
751static void
752writevar(fd, off, var)
753     int fd;
754     unsigned long off;
755     int var;
756{
757       
758  if (lseek(fd, off, L_SET) == -1)
759    {
760      (void) fprintf(stderr, "%s: lseek fails: ", progname);
761      perror("");
762      exit(1);
763    }
764  if (write(fd, (char *)&var, sizeof(int)) != sizeof(int))
765    {
766      (void) fprintf(stderr, "%s: write fails: ", progname);
767      perror("");
768      exit(1);
769    }
770  return;
771}
772
773
774/*
775 * readvar - read a variable from the file
776 */
777static void
778readvar(fd, off, var)
779     int fd;
780     unsigned long off;
781     int *var;
782{
783  int i;
784       
785  if (lseek(fd, off, L_SET) == -1)
786    {
787      (void) fprintf(stderr, "%s: lseek fails: ", progname);
788      perror("");
789      exit(1);
790    }
791  i = read(fd, (char *)var, sizeof(int));
792  if (i < 0)
793    {
794      (void) fprintf(stderr, "%s: read fails: ", progname);
795      perror("");
796      exit(1);
797    }
798  if (i != sizeof(int))
799    {
800      (void) fprintf(stderr, "%s: read expected %d, got %d\n",
801                     progname, (int)sizeof(int), i);
802      exit(1);
803    }
804  return;
805}
806#endif /* not Linux */
Note: See TracBrowser for help on using the repository browser.