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 */