PageRenderTime 31ms CodeModel.GetById 2ms app.highlight 24ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/util/tickadj.c

https://bitbucket.org/freebsd/freebsd-head/
C | 902 lines | 773 code | 94 blank | 35 comment | 142 complexity | ee5f48cb18a7be54e1fcf1c57b01eb6a MD5 | raw file
  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>
 27struct timex txc;
 28
 29#if 0
 30int
 31main(
 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
104int
105main(
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
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 */