xref: /netbsd/external/bsd/ntp/dist/util/tickadj.c (revision 6550d01e)
1 /*	$NetBSD: tickadj.c,v 1.1.1.1 2009/12/13 16:57:30 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 # include <sys/var.h>
186 #endif
187 
188 #include "ntp_stdlib.h"
189 #include "ntp_io.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	(off_t *, off_t *, off_t *, off_t *);
231 static	int	openfile	(const char *, int);
232 static	void	writevar	(int, off_t, int);
233 static	void	readvar		(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>: %s\n",
761 				       progname, *kname, strerror(errno));
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