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