]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/util/tickadj.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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_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 */