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