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