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 "ntp_types.h" 23 #include "l_stdlib.h" 24 25 #ifdef HAVE___ADJTIMEX /* Linux */ 26 27 #include <sys/timex.h> 28 struct timex txc; 29 30 #if 0 31 int 32 main( 33 int argc, 34 char *argv[] 35 ) 36 { 37 int c, i; 38 int quiet = 0; 39 int errflg = 0; 40 char *progname; 41 extern int ntp_optind; 42 extern char *ntp_optarg; 43 44 progname = argv[0]; 45 if (argc==2 && argv[1][0] != '-') { /* old Linux format, for compatability */ 46 if ((i = atoi(argv[1])) > 0) { 47 txc.time_tick = i; 48 txc.modes = ADJ_TIMETICK; 49 } else { 50 fprintf(stderr, "Silly value for tick: %s\n", argv[1]); 51 errflg++; 52 } 53 } else { 54 while ((c = ntp_getopt(argc, argv, "a:qt:")) != EOF) { 55 switch (c) { 56 case 'a': 57 if ((i=atoi(ntp_optarg)) > 0) { 58 txc.tickadj = i; 59 txc.modes |= ADJ_TICKADJ; 60 } else { 61 (void) fprintf(stderr, 62 "%s: unlikely value for tickadj: %s\n", 63 progname, ntp_optarg); 64 errflg++; 65 } 66 break; 67 68 case 'q': 69 quiet = 1; 70 break; 71 72 case 't': 73 if ((i=atoi(ntp_optarg)) > 0) { 74 txc.time_tick = i; 75 txc.modes |= ADJ_TIMETICK; 76 } else { 77 (void) fprintf(stderr, 78 "%s: unlikely value for tick: %s\n", 79 progname, ntp_optarg); 80 errflg++; 81 } 82 break; 83 84 default: 85 fprintf(stderr, 86 "Usage: %s [tick_value]\n-or- %s [ -q ] [ -t tick ] [ -a tickadj ]\n", 87 progname, progname); 88 errflg++; 89 break; 90 } 91 } 92 } 93 94 if (!errflg) { 95 if (__adjtimex(&txc) < 0) 96 perror("adjtimex"); 97 else if (!quiet) 98 printf("tick = %ld\ntick_adj = %d\n", 99 txc.time_tick, txc.tickadj); 100 } 101 102 exit(errflg ? 1 : 0); 103 } 104 #else 105 int 106 main( 107 int argc, 108 char *argv[] 109 ) 110 { 111 if (argc > 2) 112 { 113 fprintf(stderr, "Usage: %s [tick_value]\n", argv[0]); 114 exit(-1); 115 } 116 else if (argc == 2) 117 { 118 #ifdef ADJ_TIMETICK 119 if ( (txc.time_tick = atoi(argv[1])) < 1 ) 120 #else 121 if ( (txc.tick = atoi(argv[1])) < 1 ) 122 #endif 123 { 124 fprintf(stderr, "Silly value for tick: %s\n", argv[1]); 125 exit(-1); 126 } 127 #ifdef ADJ_TIMETICK 128 txc.modes = ADJ_TIMETICK; 129 #else 130 #ifdef MOD_OFFSET 131 txc.modes = ADJ_TICK; 132 #else 133 txc.mode = ADJ_TICK; 134 #endif 135 #endif 136 } 137 else 138 { 139 #ifdef ADJ_TIMETICK 140 txc.modes = 0; 141 #else 142 #ifdef MOD_OFFSET 143 txc.modes = 0; 144 #else 145 txc.mode = 0; 146 #endif 147 #endif 148 } 149 150 if (__adjtimex(&txc) < 0) 151 { 152 perror("adjtimex"); 153 } 154 else 155 { 156 #ifdef ADJ_TIMETICK 157 printf("tick = %ld\ntick_adj = %ld\n", txc.time_tick, txc.tickadj); 158 #else 159 printf("tick = %ld\n", txc.tick); 160 #endif 161 } 162 163 exit(0); 164 } 165 #endif 166 167 #else /* not Linux... kmem tweaking: */ 168 169 #ifdef HAVE_SYS_FILE_H 170 # include <sys/file.h> 171 #endif 172 #include <sys/stat.h> 173 174 #ifdef HAVE_SYS_PARAM_H 175 # include <sys/param.h> 176 #endif 177 178 #ifdef NLIST_STRUCT 179 # include <nlist.h> 180 #else /* not NLIST_STRUCT */ /* was defined(SYS_AUX3) || defined(SYS_AUX2) */ 181 # include <sys/time.h> 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_io.h" 189 #include "ntp_stdlib.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 P((off_t *, off_t *, off_t *, off_t *)); 231 static int openfile P((const char *, int)); 232 static void writevar P((int, off_t, int)); 233 static void readvar P((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>: %m\n", 761 progname, *kname); 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