1132451Sroberto/* Copyright (C) 1996 N.M. Maclaren 2132451Sroberto Copyright (C) 1996 The University of Cambridge 3132451Sroberto 4132451SrobertoThis includes all of the code needed to handle the time. It assumes rather 5132451Srobertomore than is defined by POSIX, unfortunately. Systems that do not have the 6132451Sroberto'X/Open' extensions may need changes. */ 7132451Sroberto 8132451Sroberto 9132451Sroberto 10132451Sroberto#include "header.h" 11132451Sroberto 12132451Sroberto#include <sys/types.h> 13132451Sroberto#include <sys/time.h> 14132451Sroberto 15132451Sroberto#define TIMING 16132451Sroberto#include "kludges.h" 17132451Sroberto#undef TIMING 18132451Sroberto 19132451Sroberto 20132451Sroberto 21132451Sroberto#define MILLION_L 1000000l /* For conversion to/from timeval */ 22132451Sroberto#define MILLION_D 1.0e6 /* Must be equal to MILLION_L */ 23132451Sroberto 24132451Sroberto 25132451Sroberto 26132451Srobertodouble current_time (double offset) { 27132451Sroberto 28132451Sroberto/* Get the current UTC time in seconds since the Epoch plus an offset (usually 29132451Srobertothe time from the beginning of the century to the Epoch!) */ 30132451Sroberto 31132451Sroberto struct timeval current; 32132451Sroberto 33132451Sroberto errno = 0; 34132451Sroberto if (gettimeofday(¤t,NULL)) 35132451Sroberto fatal(1,"unable to read current machine/system time",NULL); 36132451Sroberto return offset+current.tv_sec+1.0e-6*current.tv_usec; 37132451Sroberto} 38132451Sroberto 39132451Sroberto 40132451Sroberto 41132451Srobertotime_t convert_time (double value, int *millisecs) { 42132451Sroberto 43132451Sroberto/* Convert the time to the ANSI C form. */ 44132451Sroberto 45132451Sroberto time_t result = (time_t)value; 46132451Sroberto 47132451Sroberto if ((*millisecs = (int)(1000.0*(value-result))) >= 1000) { 48132451Sroberto *millisecs = 0; 49132451Sroberto ++result; 50132451Sroberto } 51132451Sroberto return result; 52132451Sroberto} 53132451Sroberto 54132451Sroberto 55132451Sroberto 56132451Srobertovoid adjust_time (double difference, int immediate, double ignore) { 57132451Sroberto 58132451Sroberto/* Adjust the current UTC time. This is portable, even if struct timeval uses 59132451Srobertoan unsigned long for tv_sec. */ 60132451Sroberto 61132451Sroberto struct timeval old, new, adjust, previous; 62132451Sroberto char text[40]; 63132451Sroberto long n; 64132451Sroberto 65132451Sroberto/* Start by converting to timeval format. Note that we have to cater for 66132451Srobertonegative, unsigned values. */ 67132451Sroberto 68132451Sroberto if ((n = (long)difference) > difference) --n; 69132451Sroberto adjust.tv_sec = n; 70132451Sroberto adjust.tv_usec = (long)(MILLION_D*(difference-n)); 71132451Sroberto errno = 0; 72132451Sroberto if (gettimeofday(&old,NULL)) 73132451Sroberto fatal(1,"unable to read machine/system time",NULL); 74132451Sroberto new.tv_sec = old.tv_sec+adjust.tv_sec; 75132451Sroberto new.tv_usec = (n = (long)old.tv_usec+(long)adjust.tv_usec); 76132451Sroberto if (n < 0) { 77132451Sroberto new.tv_usec += MILLION_L; 78132451Sroberto --new.tv_sec; 79132451Sroberto } else if (n >= MILLION_L) { 80132451Sroberto new.tv_usec -= MILLION_L; 81132451Sroberto ++new.tv_sec; 82132451Sroberto } 83132451Sroberto 84132451Sroberto/* Now diagnose the situation if necessary, and perform the dirty deed. */ 85132451Sroberto 86132451Sroberto if (verbose > 2) 87132451Sroberto fprintf(stderr, 88132451Sroberto "Times: old=(%ld,%.6ld) new=(%ld,%.6ld) adjust=(%ld,%.6ld)\n", 89132451Sroberto (long)old.tv_sec,(long)old.tv_usec, 90132451Sroberto (long)new.tv_sec,(long)new.tv_usec, 91132451Sroberto (long)adjust.tv_sec,(long)adjust.tv_usec); 92132451Sroberto if (immediate) { 93132451Sroberto errno = 0; 94182007Sroberto if (settimeofday(&new,NULL)) 95182007Sroberto fatal(1,"unable to reset current system time",NULL); 96132451Sroberto } else { 97182007Sroberto previous.tv_sec = 0; 98182007Sroberto previous.tv_usec = 0; 99132451Sroberto errno = 0; 100182007Sroberto if (adjtime(&adjust,&previous)) 101182007Sroberto fatal(1,"unable to adjust current system time",NULL); 102132451Sroberto if (previous.tv_sec != 0 || previous.tv_usec != 0) { 103132451Sroberto sprintf(text,"(%ld,%.6ld)", 104132451Sroberto (long)previous.tv_sec,(long)previous.tv_usec); 105132451Sroberto if (previous.tv_sec+1.0e-6*previous.tv_usec > ignore) 106132451Sroberto fatal(0,"outstanding time adjustment %s",text); 107132451Sroberto else if (verbose) 108132451Sroberto fprintf(stderr,"%s: outstanding time adjustment %s\n", 109132451Sroberto argv0,text); 110132451Sroberto } 111132451Sroberto } 112132451Sroberto} 113