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