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