[an error occurred while processing this directive]

HP OpenVMS Systems

ask the wizard
Content starts here

C programs and timekeeping?

» close window

The Question is:

 
Dear Wizard,
We have a client program written in C that utilizes times to determine
 connection states. The code uses ctime and sys$getim for these calculations.
 Every so often, we will get a date "17-NOV-1858 00:00:00.00" and others with a
 completely irrelevant time "
17-NOV-1858 00:02:01.45". This prompted us to write a simplistic program that
 basicaaly makes a CTIME and SYS$GETTIM call every 5 seconds and writes output
 to a log file (Code enclosed for your reference). Our question is why do we
 periodically get the ba
se date (or variation of)returned?
 
---------------------------------------
 
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <starlet.h>
#include "procinfo.h"
#include "vmsdt.h"
#include <lib$routines.h>
#include <unistd.h>
 
int main
 
    void
 
 
    float seconds = 5.0;
 
    char command[256];
    char timeBuffer[80];
    char *p;
    VMSDateTime today = {0,0};
    int returnStatus;
    VMSDateTime datetime;
 
    char m_buffer[80];
    unsigned short length;
    Descriptor oBufferD = {25, 0, m_buffer};
 
    FILE *fp = fopen("dtmmon:Time_Stamp_File.log","w","shr=get");
 
 
    time_t now ;                      /* Get the current date time */
 
one_more_time:
 
    now = time(0);                    /* Get the current date time */
 
    strcpy(timeBuffer, ctime(&now));  /* Put it in the buffer in human readable
 form */
 
    p = strchr(timeBuffer,'\n');      /* Find the end of line */
 
    if (p != NULL)                    /* And if it is found */
    {
        *p = ' ';                     /* Replace it by a space */
    }
 
    timeBuffer[19] = '\0';            /* Remove the year */
 
    fprintf(fp," \n");
    fprintf(fp,"Time using ctime(0)    - %s \n",timeBuffer + 4);
                                            /* and timestamp the output */
 
    returnStatus = sys$gettim(today);
    if (returnStatus == SS$_NORMAL)
    {
        strncpy(datetime, today, 8);
 
        returnStatus = sys$asctim(&length,&oBufferD,datetime,0);
        if (returnStatus == SS$_NORMAL)
        {
            m_buffer[length] = '\0';
            fprintf(fp,"Time using sys$gettim  - %s \n ",m_buffer);
 
            if ((strstr(&m_buffer[0],"17-NOV-1858")) != NULL)
            {
                sprintf (command,"mail nl:[].; peoples/subj=\"Base Date
 Detected");
                system (command);
            }
        }
        else
        {
            fprintf(fp,"Bad Status return from sys$asctim  - %d \n
 ",returnStatus);
        }
    }
    else
    {
        fprintf(fp,"Bad Status return from sys$gettim  - %d \n ",returnStatus);
    }
 
    fsync(fileno(fp));
 
    lib$wait (&seconds);
    goto one_more_time;
 
 
---------------------------------------
 
This is a snipit of the log we are creating...
 
Time using ctime(0)    - Apr 13 12:49:22
Time using sys$gettim  - 13-APR-2004 11:49:22.04
 
Time using ctime(0)    - Apr 13 12:49:27
Time using sys$gettim  - 13-APR-2004 11:49:27.04
 
Time using ctime(0)    - Apr 13 12:49:32
Time using sys$gettim  - 13-APR-2004 11:49:32.04
 
Time using ctime(0)    - Apr 13 12:49:37
Time using sys$gettim  - 17-NOV-1858 00:00:00.00
 
Time using ctime(0)    - Apr 13 12:49:42
Time using sys$gettim  - 13-APR-2004 11:49:42.22
 
Time using ctime(0)    - Apr 13 12:49:47
Time using sys$gettim  - 13-APR-2004 11:49:47.22
 
Time using ctime(0)    - Apr 13 12:49:52
Time using sys$gettim  - 13-APR-2004 11:49:52.23
 
Time using ctime(0)    - Apr 13 12:49:57
Time using sys$gettim  - 13-APR-2004 11:49:57.23
---------------------------------------
 
Thanks in advance Wizard...


The Answer is :

 
  The central problem is in the following C statement:
 
        strncpy(datetime, today, 8);
 
  strncpy copies up to, but not including the null terminator of
  the source string for a maximum of 8 characters.  If the length
  of the source string (today, here) is less than that of the
  target (datetime, here), then the target string will have a null
  and (usually) some bytes left over from the stack or the previous
  contents of datetime variable.
 
  Should the time contain a null byte (which can certainly happen,
  and with some frequency), or should there be no null at the end
  of the today string, then the str-class functions can copy too
  little or too much data.  strncpy does limit the amount of data
  that can be transfered, but strcpy can sometimes copy rather
  more data than intended or can fail outright when the source
  string is not properly null-terminated.  str-class functions
  can also fail with data referenced by string descriptors, as
  the strings involved are not necessarily null-terminated.
 
  memcpy would be preferable for a copy of binary data, or the use
  of the long long or __int64 construct and an assignment statement
  can be of interest for those configurations and compilers
  that support it.  All OpenVMS C compilers also support a pair
  of longwords in an array, and the assignment of same.
 
  17-Nov-1858 is the system base date, as referenced in the
  OpenVMS FAQ.  The system base date in native time quadword
  format is a quadword zero.  Additional details and related
  background are included in the FAQ.
 
  For new applications or non-trivial-scale updates to existing
  applications, the OpenVMS Wizard would encourage use of UTC
  services or UTC C library calls.  Native time has limitations
  around the Timezone Differential Factor (TDF) and timezones.
  C native time has limitations around the scale of the longword,
  as common C calls use the number of seconds since 1980 and
  this value will obviously overflow circa 2038 and quite
  possibly sooner depending on the manipulations and the use of
  signed values.
 
  The OpenVMS Wizard will discourage the use of the localtime as
  a key value for a transaction long or indexed file, as it is
  not unique (beyond the ganularity of the system clock ticks)
  and (with daylight savings) may not be a uniformly and
  perpetually increasing value.
 
  For applications that use localtime, the TDF change event
  available in recent OpenVMS releases can also be of
  interest.  This event allows applications to be notified
  whenthe daylight savings time switch (to or from standard
  time) occurs.
 
  For discussions of time and for discussions of common C
  coding mistakes, please see the OpeNVMS FAQ.  Also please
  see the discussions of common coding mistakes here in topic
  (1661) and other topics referenced there.  (In the experience
  of the OpenVMS Wizard, time and timekeeping is far more
  interesting and involved and detailed than it might initially
  appear, and null bytes latent within the native quadword time
  value are just one small aspect of time and timekeeping.)
 
  Depending on the declaration of Descriptor used within
  the application, there may well be an additional bug.
  Use of descrip.h and the $DESCRIPTOR macro and.or the
  dsc structures and constants is more commonly expected.
  In particular, please see the discussions of string
  descriptors and of padding within the OpenVMS FAQ.
 
  You can also default the quadword time argument to sys$asctim,
  and get it to return the current system time in ASCII format.
  Various of the example can be completely eliminated, in other
  words.  For example, the following uses the current time:
 
    ReturnStatus = sys$asctim( NULL, OutputBufferDsc, NULL, 0 );
 
  Also note that the internal implementations of C and OpenVMS
  timekeeping -- while based on the same internal values -- can
  and do differ.  In particular, please see the off-by-an-hour
  discussion in the OpenVMS FAQ.
 
  OpenVMS Freeware V5.0 directory srh_examples examples include
  dsbd.c and various other time-calling examples located there,
  as well as various examples in the Programming Concepts
  Manual and in the C programming documentation.  There are
  also pointers to available examples located in the FAQ.
 

answer written or last revised on ( 13-APR-2004 )

» close window