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