endofepoch.c
Jeg børstet støvet av noen tilårskomne filer forleden dag. Jeg fant et lite program som jeg skrev en gang i 2000. Programmet teller ned til slutten av Unix-epoken.
Den opprinnelige definisjonen av datatypen time_t
, 32-bit heltall med fortegn, vil få overflyt i midten av januar 2038. Moderne 64-bit OS som FreeBSD/amd64 9.0 har for lengst gått over til 64-bit time_t
. Bare ta en titt i fila /usr/src/sys/amd64/include/_types.h
, omtrent ved linje 83. Problemet med overflyten i år 2038 vil fortsatt gjelde alt utstyr og (binære) filformater som bruker den gamle definisjonen, slik som FreeBSD/i386 9.0. Ta en titt i fila /usr/src/sys/i386/include/_types.h
, omtrent ved linje 91. Den engelske utgaven av Wikipedia har en utfyllende artikkel om problemet.
Kildekoden for det søte, lille programmet mitt, er gjengitt under.
/* endofepoch.c -- Et program som teller ned til slutten på Unix-epoken, med mindre størrelsen til time_t endres eller nullpunktet flyttes. Copyright (C) 2000 Trond Endrestøl <Trond.Endrestol@ximalas.info> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include <sys/time.h> #include <sys/resource.h> #include <limits.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> volatile int Avslutt = 1; void VisHjelp(const char * const argv0, int Returverdi); void VisVersjon(void); const char *FinnProgramnavn(const char * const argv0); void Signalrutine(int Signal) { #if defined(unix) && !defined(__DJGPP__) if (Signal == SIGINT) { fflush(stderr); fflush(stdout); fputs("\b \b\b \b", stdout); fflush(stdout); } /* if */ #endif Avslutt = 1; } /* Signalrutine() */ int main(int argc, char **argv) { #if __FreeBSD__ > 4 && __amd64__ == 1 const time_t Slutten = INT_MAX; #else const time_t Slutten = LONG_MAX; #endif const time_t SekunderPrDag = 86400L; const time_t SekunderPrTime = 3600L; const time_t SekunderPrMinutt = 60L; time_t TidenSomGjenstaar, Dager, Timer, Minutter; int AntTegn; opterr = 0; while (1) { int c; c = getopt(argc, argv, "ihv"); if (c == -1) { break; } /* if */ switch (c) { case 'i': Avslutt = 0; break; case 'h': VisHjelp(argv[0], 0); break; case '?': VisHjelp(argv[0], 1); break; case 'v': VisVersjon(); break; } /* switch */ } /* while */ if (!Avslutt) { setpriority(PRIO_PROCESS, 0, 1); signal(SIGHUP, Signalrutine); signal(SIGINT, Signalrutine); signal(SIGQUIT, Signalrutine); signal(SIGTERM, Signalrutine); } /* if */ do { TidenSomGjenstaar = Slutten - time(NULL); Dager = TidenSomGjenstaar / SekunderPrDag; TidenSomGjenstaar -= Dager * SekunderPrDag; Timer = TidenSomGjenstaar / SekunderPrTime; TidenSomGjenstaar -= Timer * SekunderPrTime; Minutter = TidenSomGjenstaar / SekunderPrMinutt; TidenSomGjenstaar -= Minutter * SekunderPrMinutt; AntTegn = printf("%ld dag%s, %02ld:%02ld:%02ld igjen til slutten på Unix-epoken.", Dager, (Dager == 1) ? "" : "er", Timer, Minutter, TidenSomGjenstaar); fflush(stdout); /* Signalrutine() kan bli kjørt mens main() sover. Derfor er det to if-setninger etter hverandre, med samme betingelse! */ if (!Avslutt) { sleep(1); } /* if */ if (!Avslutt) { while (AntTegn--) { fputs("\b \b", stdout); } /* while */ } /* if */ } while (!Avslutt); /* do-while */ #if defined(unix) && !defined(__DJGPP__) puts(""); #endif return 0; } /* main() */ void VisHjelp(const char * const argv0, int Returverdi) { fprintf((Returverdi == 0) ? stdout : stderr, "Bruksmåte: %s [-i] [-h] [-v]\n\n" "Programmet teller ned dager, timer, minutter og sekunder\n" "til slutten av Unix-epoken.\n\n" "-i Kjøre flere runder.\n" "-h Vise denne hjelpen.\n" "-v Vise programversjon.\n", FinnProgramnavn(argv0)); exit(Returverdi); } /* VisHjelp() */ void VisVersjon(void) { const char * const Programversjon = "endofepoch versjon 1.0 ble kompilert " __DATE__ " " __TIME__ "\nav " #if defined __GNUC__ "GNU CC versjon " __VERSION__ #elif defined __BORLANDC__ "Borland C" #else "en ukjent kompillator" #endif ".\n" "Copyright (C) 2000 Trond Endrestøl <Trond.Endrestol@ximalas.info>.\n" "endofepoch distribueres under GNU General Public License versjon 2\n" "eller nyere, se filen COPYING."; /* Programversjon */ puts(Programversjon); exit(0); } /* VisVersjon() */ const char *FinnProgramnavn(const char * const argv0) { const char *Peker; if ( (Peker = strrchr(argv0, '/')) == NULL) { if ( (Peker = strrchr(argv0, '\\')) == NULL) { Peker = argv0; } /* if */ } /* if */ if (Peker != argv0) { Peker++; } /* if */ return Peker; } /* FinnProgramnavn() */ /* endofepoch.c */