1 /* $NetBSD: tickadj.c,v 1.1.1.1 2009/12/13 16:57:30 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 # include <sys/var.h> 186 #endif 187 188 #include "ntp_stdlib.h" 189 #include "ntp_io.h" 190 191 #ifdef hz /* Was: RS6000 */ 192 # undef hz 193 #endif /* hz */ 194 195 #ifdef HAVE_KVM_OPEN 196 # include <kvm.h> 197 #endif 198 199 #ifdef SYS_VXWORKS 200 /* vxWorks needs mode flag -casey*/ 201 #define open(name, flags) open(name, flags, 0777) 202 #endif 203 204 #ifndef L_SET /* Was: defined(SYS_PTX) || defined(SYS_IX86OSF1) */ 205 # define L_SET SEEK_SET 206 #endif 207 208 #ifndef HZ 209 # define HZ DEFAULT_HZ 210 #endif 211 212 #define KMEM "/dev/kmem" 213 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) 214 215 char *progname; 216 volatile int debug; 217 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; 225 226 const char *kmem = KMEM; 227 const char *file = NULL; 228 int fd = -1; 229 230 static void getoffsets (off_t *, off_t *, off_t *, off_t *); 231 static int openfile (const char *, int); 232 static void writevar (int, off_t, int); 233 static void readvar (int, off_t, int *); 234 235 /* 236 * main - parse arguments and handle options 237 */ 238 int 239 main( 240 int argc, 241 char *argv[] 242 ) 243 { 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; 258 259 progname = argv[0]; 260 while ((c = ntp_getopt(argc, argv, "a:Adkpqst:")) != EOF) 261 { 262 switch (c) 263 { 264 case 'a': 265 writetickadj = atoi(ntp_optarg); 266 if (writetickadj <= 0) 267 { 268 (void) fprintf(stderr, 269 "%s: unlikely value for tickadj: %s\n", 270 progname, ntp_optarg); 271 errflg++; 272 } 273 274 #if defined SCO5_CLOCK 275 if (writetickadj % HZ) 276 { 277 writetickadj = (writetickadj / HZ) * HZ; 278 (void) fprintf(stderr, 279 "tickadj truncated to: %d\n", writetickadj); 280 } 281 #endif /* SCO5_CLOCK */ 282 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) 305 { 306 (void) fprintf(stderr, 307 "%s: unlikely value for tick: %s\n", 308 progname, ntp_optarg); 309 errflg++; 310 } 311 break; 312 default: 313 errflg++; 314 break; 315 } 316 } 317 if (errflg || ntp_optind != argc) 318 { 319 (void) fprintf(stderr, 320 "usage: %s [-Adkpqs] [-a newadj] [-t newtick]\n", progname); 321 exit(2); 322 } 323 324 getoffsets(&tick_offset, &tickadj_offset, &dosync_offset, &noprintf_offset); 325 326 if (debug) 327 { 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); 332 } 333 334 if (writetick && (tick_offset == 0)) 335 { 336 (void) fprintf(stderr, 337 "No tick kernel variable\n"); 338 errflg++; 339 } 340 341 if (writeopttickadj && (tickadj_offset == 0)) 342 { 343 (void) fprintf(stderr, 344 "No tickadj kernel variable\n"); 345 errflg++; 346 } 347 348 if (unsetdosync && (dosync_offset == 0)) 349 { 350 (void) fprintf(stderr, 351 "No dosynctodr kernel variable\n"); 352 errflg++; 353 } 354 355 if (setnoprintf && (noprintf_offset == 0)) 356 { 357 (void) fprintf(stderr, 358 "No noprintf kernel variable\n"); 359 errflg++; 360 } 361 362 if (tick_offset != 0) 363 { 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 */ 369 370 #ifdef TICK_NANO 371 tick /= 1000; 372 #endif 373 } 374 else 375 { 376 tick = 0; 377 } 378 379 if (tickadj_offset != 0) 380 { 381 readvar(fd, tickadj_offset, &tickadj); 382 383 #ifdef SCO5_CLOCK 384 /* scale from nsec/sec to usec/tick */ 385 tickadj /= (1000L * HZ); 386 #endif /*SCO5_CLOCK */ 387 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 */ 392 393 #ifdef TICKADJ_NANO 394 tickadj += 999; 395 tickadj /= 1000; 396 #endif 397 } 398 else 399 { 400 tickadj = 0; 401 } 402 403 if (dosync_offset != 0) 404 { 405 readvar(fd, dosync_offset, &dosynctodr); 406 } 407 408 if (noprintf_offset != 0) 409 { 410 readvar(fd, noprintf_offset, &noprintf); 411 } 412 413 (void) close(fd); 414 415 if (unsetdosync && dosync_offset == 0) 416 { 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 */ 425 ); 426 exit(1); 427 } 428 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 */ 449 450 if (!quiet) 451 { 452 if (tick_offset != 0) 453 { 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 461 ); 462 } 463 #ifdef PRESET_TICK 464 (void) printf("PRESET tick = %d usec\n", tick); 465 #endif /* PRESET_TICK */ 466 if (tickadj_offset != 0) 467 { 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 475 ); 476 } 477 #ifdef PRESET_TICKADJ 478 (void) printf("PRESET tickadj = %d usec\n", tickadj); 479 #endif /* PRESET_TICKADJ */ 480 if (dosync_offset != 0) 481 { 482 (void) printf("dosynctodr is %s\n", dosynctodr ? "on" : "off"); 483 } 484 if (noprintf_offset != 0) 485 { 486 (void) printf("kernel level printf's: %s\n", 487 noprintf ? "off" : "on"); 488 } 489 } 490 491 if (tick <= 0) 492 { 493 (void) fprintf(stderr, "%s: the value of tick is silly!\n", 494 progname); 495 exit(1); 496 } 497 498 hz_int = (int)(1000000L / (long)tick); 499 hz_hundredths = (int)((100000000L / (long)tick) - ((long)hz_int * 100L)); 500 if (!quiet) 501 { 502 (void) printf("KERNEL hz = %d\n", hz); 503 (void) printf("calculated hz = %d.%02d Hz\n", hz_int, 504 hz_hundredths); 505 } 506 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) 513 { 514 recommend_tickadj++; 515 } 516 517 #ifdef MIN_REC_TICKADJ 518 if (recommend_tickadj < MIN_REC_TICKADJ) 519 { 520 recommend_tickadj = MIN_REC_TICKADJ; 521 } 522 #endif /* MIN_REC_TICKADJ */ 523 #endif /* SCO5_CLOCK */ 524 525 526 if ((!quiet) && (tickadj_offset != 0)) 527 { 528 (void) printf("recommended value of tickadj = %d us\n", 529 recommend_tickadj); 530 } 531 532 if ( writetickadj == 0 533 && !writeopttickadj 534 && !unsetdosync 535 && writetick == 0 536 && !setnoprintf) 537 { 538 exit(errflg ? 1 : 0); 539 } 540 541 if (writetickadj == 0 && writeopttickadj) 542 { 543 writetickadj = recommend_tickadj; 544 } 545 546 fd = openfile(file, O_WRONLY); 547 548 if (setnoprintf && (noprintf_offset != 0)) 549 { 550 if (!quiet) 551 { 552 (void) fprintf(stderr, "setting noprintf: "); 553 (void) fflush(stderr); 554 } 555 writevar(fd, noprintf_offset, 1); 556 if (!quiet) 557 { 558 (void) fprintf(stderr, "done!\n"); 559 } 560 } 561 562 if ((writetick > 0) && (tick_offset != 0)) 563 { 564 if (!quiet) 565 { 566 (void) fprintf(stderr, "writing tick, value %d: ", 567 writetick); 568 (void) fflush(stderr); 569 } 570 writevar(fd, tick_offset, writetick); 571 if (!quiet) 572 { 573 (void) fprintf(stderr, "done!\n"); 574 } 575 } 576 577 if ((writetickadj > 0) && (tickadj_offset != 0)) 578 { 579 if (!quiet) 580 { 581 (void) fprintf(stderr, "writing tickadj, value %d: ", 582 writetickadj); 583 (void) fflush(stderr); 584 } 585 586 #ifdef SCO5_CLOCK 587 /* scale from usec/tick to nsec/sec */ 588 writetickadj *= (1000L * HZ); 589 #endif /* SCO5_CLOCK */ 590 591 writevar(fd, tickadj_offset, writetickadj); 592 if (!quiet) 593 { 594 (void) fprintf(stderr, "done!\n"); 595 } 596 } 597 598 if (unsetdosync && (dosync_offset != 0)) 599 { 600 if (!quiet) 601 { 602 (void) fprintf(stderr, "zeroing dosynctodr: "); 603 (void) fflush(stderr); 604 } 605 writevar(fd, dosync_offset, 0); 606 if (!quiet) 607 { 608 (void) fprintf(stderr, "done!\n"); 609 } 610 } 611 (void) close(fd); 612 return(errflg ? 1 : 0); 613 } 614 615 /* 616 * getoffsets - read the magic offsets from the specified file 617 */ 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 624 ) 625 { 626 627 #ifndef NOKMEM 628 # ifndef HAVE_KVM_OPEN 629 const char **kname; 630 # endif 631 #endif 632 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 642 643 #define K_FILLER_NAME "DavidLetterman" 644 645 #ifdef NLIST_EXTRA_INDIRECTION 646 int i; 647 #endif 648 649 #ifndef NOKMEM 650 static struct nlist nl[] = 651 { 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, 685 }; 686 687 #ifndef HAVE_KVM_OPEN 688 static const char *kernels[] = 689 { 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 704 }; 705 #endif /* not HAVE_KVM_OPEN */ 706 707 #ifdef HAVE_KVM_OPEN 708 /* 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 711 */ 712 kvm_t *kvm_handle = kvm_open(NULL, NULL, NULL, O_RDONLY, progname); 713 714 if (kvm_handle == NULL) 715 { 716 (void) fprintf(stderr, 717 "%s: kvm_open failed\n", 718 progname); 719 exit(1); 720 } 721 if (kvm_nlist(kvm_handle, nl) == -1) 722 { 723 (void) fprintf(stderr, 724 "%s: kvm_nlist failed\n", 725 progname); 726 exit(1); 727 } 728 kvm_close(kvm_handle); 729 #else /* not HAVE_KVM_OPEN */ 730 #ifdef HAVE_GETBOOTFILE /* *** SEE HERE! *** */ 731 if (kernels[0] == NULL) 732 { 733 char * cp = (char *)getbootfile(); 734 735 if (cp) 736 { 737 kernels[0] = cp; 738 } 739 else 740 { 741 kernels[0] = "/Placeholder"; 742 } 743 } 744 #endif /* HAVE_GETBOOTFILE */ 745 for (kname = kernels; *kname != NULL; kname++) 746 { 747 struct stat stbuf; 748 749 if (stat(*kname, &stbuf) == -1) 750 { 751 continue; 752 } 753 if (nlist(*kname, nl) >= 0) 754 { 755 break; 756 } 757 else 758 { 759 (void) fprintf(stderr, 760 "%s: nlist didn't find needed symbols from <%s>: %s\n", 761 progname, *kname, strerror(errno)); 762 } 763 } 764 if (*kname == NULL) 765 { 766 (void) fprintf(stderr, 767 "%s: Couldn't find the kernel\n", 768 progname); 769 exit(1); 770 } 771 #endif /* HAVE_KVM_OPEN */ 772 773 if (dokmem) 774 { 775 file = kmem; 776 777 fd = openfile(file, O_RDONLY); 778 #ifdef NLIST_EXTRA_INDIRECTION 779 /* 780 * Go one more round of indirection. 781 */ 782 for (i = 0; i < (sizeof(nl) / sizeof(struct nlist)); i++) 783 { 784 if ((nl[i].n_value) && (nl[i].n_sclass == 0x6b)) 785 { 786 readvar(fd, nl[i].n_value, &nl[i].n_value); 787 } 788 } 789 #endif /* NLIST_EXTRA_INDIRECTION */ 790 } 791 #endif /* not NOKMEM */ 792 793 *tickadj_off = 0; 794 *tick_off = 0; 795 *dosync_off = 0; 796 *noprintf_off = 0; 797 798 #if defined(N_TICKADJ) 799 *tickadj_off = nl[N_TICKADJ].n_value; 800 #endif 801 802 #if defined(N_TICK) 803 *tick_off = nl[N_TICK].n_value; 804 #endif 805 806 #if defined(N_DOSYNC) 807 *dosync_off = nl[N_DOSYNC].n_value; 808 #endif 809 810 #if defined(N_NOPRINTF) 811 *noprintf_off = nl[N_NOPRINTF].n_value; 812 #endif 813 return; 814 } 815 816 #undef N_TICKADJ 817 #undef N_TICK 818 #undef N_DOSYNC 819 #undef N_NOPRINTF 820 821 822 /* 823 * openfile - open the file, check for errors 824 */ 825 static int 826 openfile( 827 const char *name, 828 int mode 829 ) 830 { 831 int ifd; 832 833 ifd = open(name, mode); 834 if (ifd < 0) 835 { 836 (void) fprintf(stderr, "%s: open %s: ", progname, name); 837 perror(""); 838 exit(1); 839 } 840 return ifd; 841 } 842 843 844 /* 845 * writevar - write a variable into the file 846 */ 847 static void 848 writevar( 849 int ofd, 850 off_t off, 851 int var 852 ) 853 { 854 855 if (lseek(ofd, off, L_SET) == -1) 856 { 857 (void) fprintf(stderr, "%s: lseek fails: ", progname); 858 perror(""); 859 exit(1); 860 } 861 if (write(ofd, (char *)&var, sizeof(int)) != sizeof(int)) 862 { 863 (void) fprintf(stderr, "%s: write fails: ", progname); 864 perror(""); 865 exit(1); 866 } 867 return; 868 } 869 870 871 /* 872 * readvar - read a variable from the file 873 */ 874 static void 875 readvar( 876 int ifd, 877 off_t off, 878 int *var 879 ) 880 { 881 int i; 882 883 if (lseek(ifd, off, L_SET) == -1) 884 { 885 (void) fprintf(stderr, "%s: lseek fails: ", progname); 886 perror(""); 887 exit(1); 888 } 889 i = read(ifd, (char *)var, sizeof(int)); 890 if (i < 0) 891 { 892 (void) fprintf(stderr, "%s: read fails: ", progname); 893 perror(""); 894 exit(1); 895 } 896 if (i != sizeof(int)) 897 { 898 (void) fprintf(stderr, "%s: read expected %d, got %d\n", 899 progname, (int)sizeof(int), i); 900 exit(1); 901 } 902 return; 903 } 904 #endif /* not Linux */ 905