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