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