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