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