xref: /freebsd/contrib/ntp/util/tickadj.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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