1/* Copyright (C) 1996 N.M. Maclaren 2 Copyright (C) 1996 The University of Cambridge 3 4This includes all of the code needed to handle the time. It assumes rather 5more than is defined by POSIX, unfortunately. Systems that do not have the 6'X/Open' extensions may need changes. */ 7 8 9 10#include "header.h" 11 12#include <sys/types.h> 13#include <sys/time.h> 14 15#define TIMING 16#include "kludges.h" 17#undef TIMING 18 19 20 21#define MILLION_L 1000000l /* For conversion to/from timeval */ 22#define MILLION_D 1.0e6 /* Must be equal to MILLION_L */ 23 24 25 26double current_time (double offset) { 27 28/* Get the current UTC time in seconds since the Epoch plus an offset (usually 29the time from the beginning of the century to the Epoch!) */ 30 31 struct timeval current; 32 33 errno = 0; 34 if (gettimeofday(¤t,NULL)) 35 fatal(1,"unable to read current machine/system time",NULL); 36 return offset+current.tv_sec+1.0e-6*current.tv_usec; 37} 38 39 40 41time_t convert_time (double value, int *millisecs) { 42 43/* Convert the time to the ANSI C form. */ 44 45 time_t result = (time_t)value; 46 47 if ((*millisecs = (int)(1000.0*(value-result))) >= 1000) { 48 *millisecs = 0; 49 ++result; 50 } 51 return result; 52} 53 54 55 56void adjust_time (double difference, int immediate, double ignore) { 57 58/* Adjust the current UTC time. This is portable, even if struct timeval uses 59an unsigned long for tv_sec. */ 60 61 struct timeval old, new, adjust, previous; 62 char text[40]; 63 long n; 64 65/* Start by converting to timeval format. Note that we have to cater for 66negative, unsigned values. */ 67 68 if ((n = (long)difference) > difference) --n; 69 adjust.tv_sec = n; 70 adjust.tv_usec = (long)(MILLION_D*(difference-n)); 71 errno = 0; 72 if (gettimeofday(&old,NULL)) 73 fatal(1,"unable to read machine/system time",NULL); 74 new.tv_sec = old.tv_sec+adjust.tv_sec; 75 new.tv_usec = (n = (long)old.tv_usec+(long)adjust.tv_usec); 76 if (n < 0) { 77 new.tv_usec += MILLION_L; 78 --new.tv_sec; 79 } else if (n >= MILLION_L) { 80 new.tv_usec -= MILLION_L; 81 ++new.tv_sec; 82 } 83 84/* Now diagnose the situation if necessary, and perform the dirty deed. */ 85 86 if (verbose > 2) 87 fprintf(stderr, 88 "Times: old=(%ld,%.6ld) new=(%ld,%.6ld) adjust=(%ld,%.6ld)\n", 89 (long)old.tv_sec,(long)old.tv_usec, 90 (long)new.tv_sec,(long)new.tv_usec, 91 (long)adjust.tv_sec,(long)adjust.tv_usec); 92 if (immediate) { 93 errno = 0; 94 if (settimeofday(&new,NULL)) 95 fatal(1,"unable to reset current system time",NULL); 96 } else { 97 previous.tv_sec = 0; 98 previous.tv_usec = 0; 99 errno = 0; 100 if (adjtime(&adjust,&previous)) 101 fatal(1,"unable to adjust current system time",NULL); 102 if (previous.tv_sec != 0 || previous.tv_usec != 0) { 103 sprintf(text,"(%ld,%.6ld)", 104 (long)previous.tv_sec,(long)previous.tv_usec); 105 if (previous.tv_sec+1.0e-6*previous.tv_usec > ignore) 106 fatal(0,"outstanding time adjustment %s",text); 107 else if (verbose) 108 fprintf(stderr,"%s: outstanding time adjustment %s\n", 109 argv0,text); 110 } 111 } 112} 113