1226031Sstas/*
2226031Sstas * tickadj - read, and possibly modify, the kernel `tick' and
3226031Sstas *	     `tickadj' variables, as well as `dosynctodr'.  Note that
4226031Sstas *	     this operates on the running kernel only.  I'd like to be
5226031Sstas *	     able to read and write the binary as well, but haven't
6226031Sstas *	     mastered this yet.
7226031Sstas *
8226031Sstas * HMS: The #includes here are different from those in xntpd/ntp_unixclock.c
9226031Sstas *      These seem "worse".
10226031Sstas */
11226031Sstas
12226031Sstas#ifdef HAVE_CONFIG_H
13226031Sstas# include <config.h>
14226031Sstas#endif
15226031Sstas
16226031Sstas#include "ntp_types.h"
17226031Sstas#include "l_stdlib.h"
18226031Sstas
19226031Sstas#include <stdio.h>
20226031Sstas#ifdef HAVE_UNISTD_H
21226031Sstas# include <unistd.h>
22226031Sstas#endif /* HAVE_UNISTD_H */
23226031Sstas
24226031Sstas#ifdef HAVE___ADJTIMEX		/* Linux */
25226031Sstas
26226031Sstas#include <sys/timex.h>
27226031Sstasstruct timex txc;
28226031Sstas
29226031Sstas#if 0
30226031Sstasint
31226031Sstasmain(
32226031Sstas	int argc,
33226031Sstas	char *argv[]
34226031Sstas	)
35226031Sstas{
36226031Sstas	int     c, i;
37226031Sstas	int     quiet = 0;
38226031Sstas	int     errflg = 0;
39226031Sstas	char    *progname;
40226031Sstas	extern int ntp_optind;
41226031Sstas	extern char *ntp_optarg;
42226031Sstas
43226031Sstas	progname = argv[0];
44226031Sstas	if (argc==2 && argv[1][0] != '-') { /* old Linux format, for compatability */
45226031Sstas	    if ((i = atoi(argv[1])) > 0) {
46226031Sstas		    txc.time_tick = i;
47226031Sstas		    txc.modes = ADJ_TIMETICK;
48226031Sstas	    } else {
49226031Sstas		    fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
50226031Sstas		    errflg++;
51226031Sstas	    }
52226031Sstas	} else {
53226031Sstas	    while ((c = ntp_getopt(argc, argv, "a:qt:")) != EOF) {
54226031Sstas		switch (c) {
55226031Sstas		    case 'a':
56226031Sstas			if ((i=atoi(ntp_optarg)) > 0) {
57226031Sstas				txc.tickadj = i;
58226031Sstas				txc.modes |= ADJ_TICKADJ;
59226031Sstas			} else {
60226031Sstas				(void) fprintf(stderr,
61226031Sstas				       "%s: unlikely value for tickadj: %s\n",
62226031Sstas				       progname, ntp_optarg);
63226031Sstas				errflg++;
64226031Sstas			}
65226031Sstas			break;
66226031Sstas
67226031Sstas		    case 'q':
68226031Sstas			quiet = 1;
69226031Sstas			break;
70226031Sstas
71226031Sstas		    case 't':
72226031Sstas			if ((i=atoi(ntp_optarg)) > 0) {
73226031Sstas				txc.time_tick = i;
74226031Sstas				txc.modes |= ADJ_TIMETICK;
75226031Sstas			} else {
76226031Sstas				(void) fprintf(stderr,
77226031Sstas				       "%s: unlikely value for tick: %s\n",
78226031Sstas				       progname, ntp_optarg);
79226031Sstas				errflg++;
80226031Sstas			}
81226031Sstas			break;
82226031Sstas
83226031Sstas		    default:
84226031Sstas			fprintf(stderr,
85226031Sstas			    "Usage: %s [tick_value]\n-or-   %s [ -q ] [ -t tick ] [ -a tickadj ]\n",
86226031Sstas			    progname, progname);
87226031Sstas			errflg++;
88226031Sstas			break;
89226031Sstas		}
90226031Sstas	    }
91226031Sstas	}
92226031Sstas
93226031Sstas	if (!errflg) {
94226031Sstas		if (__adjtimex(&txc) < 0)
95226031Sstas			perror("adjtimex");
96226031Sstas		else if (!quiet)
97226031Sstas			printf("tick     = %ld\ntick_adj = %d\n",
98226031Sstas			    txc.time_tick, txc.tickadj);
99226031Sstas	}
100226031Sstas
101226031Sstas	exit(errflg ? 1 : 0);
102226031Sstas}
103226031Sstas#else
104226031Sstasint
105226031Sstasmain(
106226031Sstas	int argc,
107226031Sstas	char *argv[]
108226031Sstas	)
109226031Sstas{
110226031Sstas	if (argc > 2)
111226031Sstas	{
112226031Sstas		fprintf(stderr, "Usage: %s [tick_value]\n", argv[0]);
113226031Sstas		exit(-1);
114226031Sstas	}
115226031Sstas	else if (argc == 2)
116226031Sstas	{
117226031Sstas#ifdef ADJ_TIMETICK
118226031Sstas		if ( (txc.time_tick = atoi(argv[1])) < 1 )
119226031Sstas#else
120226031Sstas		if ( (txc.tick = atoi(argv[1])) < 1 )
121226031Sstas#endif
122226031Sstas		{
123226031Sstas			fprintf(stderr, "Silly value for tick: %s\n", argv[1]);
124226031Sstas			exit(-1);
125226031Sstas		}
126226031Sstas#ifdef ADJ_TIMETICK
127226031Sstas		txc.modes = ADJ_TIMETICK;
128226031Sstas#else
129226031Sstas#ifdef MOD_OFFSET
130226031Sstas		txc.modes = ADJ_TICK;
131226031Sstas#else
132226031Sstas		txc.mode = ADJ_TICK;
133226031Sstas#endif
134226128Sstas#endif
135226031Sstas	}
136226031Sstas	else
137226031Sstas	{
138226031Sstas#ifdef ADJ_TIMETICK
139226031Sstas		txc.modes = 0;
140226031Sstas#else
141226031Sstas#ifdef MOD_OFFSET
142226031Sstas		txc.modes = 0;
143226031Sstas#else
144226031Sstas		txc.mode = 0;
145226031Sstas#endif
146226031Sstas#endif
147226031Sstas	}
148226031Sstas
149226031Sstas	if (__adjtimex(&txc) < 0)
150226031Sstas	{
151226031Sstas		perror("adjtimex");
152226031Sstas	}
153226031Sstas	else
154226031Sstas	{
155226031Sstas#ifdef ADJ_TIMETICK
156226031Sstas		printf("tick     = %ld\ntick_adj = %ld\n", txc.time_tick, txc.tickadj);
157226031Sstas#else
158226031Sstas		printf("tick = %ld\n", txc.tick);
159226031Sstas#endif
160226031Sstas	}
161226031Sstas
162226031Sstas	exit(0);
163226031Sstas}
164226031Sstas#endif
165226031Sstas
166226031Sstas#else /* not Linux... kmem tweaking: */
167226031Sstas
168226031Sstas#ifdef HAVE_SYS_FILE_H
169226031Sstas# include <sys/file.h>
170226031Sstas#endif
171226031Sstas#include <sys/stat.h>
172226031Sstas
173226031Sstas#ifdef HAVE_SYS_PARAM_H
174226031Sstas# include <sys/param.h>
175226031Sstas#endif
176226031Sstas
177226031Sstas#ifdef NLIST_STRUCT
178226031Sstas# include <nlist.h>
179226031Sstas#else /* not NLIST_STRUCT */ /* was defined(SYS_AUX3) || defined(SYS_AUX2) */
180226031Sstas# include <sys/resource.h>
181226031Sstas# include <sys/file.h>
182226031Sstas# include <a.out.h>
183226031Sstas# include <sys/var.h>
184226031Sstas#endif
185226031Sstas
186226031Sstas#include "ntp_io.h"
187226031Sstas#include "ntp_stdlib.h"
188226031Sstas
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
213char *progname;
214volatile int debug;
215
216int dokmem = 1;
217int writetickadj = 0;
218int writeopttickadj = 0;
219int unsetdosync = 0;
220int writetick = 0;
221int quiet = 0;
222int setnoprintf = 0;
223
224const char *kmem = KMEM;
225const char *file = NULL;
226int   fd  = -1;
227
228static	void	getoffsets	P((off_t *, off_t *, off_t *, off_t *));
229static	int	openfile	P((const char *, int));
230static	void	writevar	P((int, off_t, int));
231static	void	readvar		P((int, off_t, int *));
232
233/*
234 * main - parse arguments and handle options
235 */
236int
237main(
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 */
616static void
617getoffsets(
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 */
823static int
824openfile(
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 */
845static void
846writevar(
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 */
872static void
873readvar(
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