]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ntp/util/tickadj.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ntp / util / tickadj.c
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 */