#if !defined(lint) && !defined(__INSIGHT__)
static char sos__rcsid[] = "time.c,v 1.1.1.1 1995/06/16 17:42:43 seth Exp";
static char sos__copyright[] = "Copyright (c) 1994, 1995 SOS Corporation";
static char sos__contact[] = "SOS Corporation <sos-info@soscorp.com> +1 800 SOS UNIX";
#endif /* not lint */

/*
 * ++Copyright Released Product++
 *
 * Copyright (c) 1994, 1995 Sources of Supply Corporation ("SOS").
 * All rights reserved.
 *
 * The SOS Released Product License Agreement specifies the terms and
 * conditions for redistribution.  You may find the License Agreement
 * in the file LICENSE.
 *
 * SOS Corporation
 * 461 5th Ave.; 16th floor
 * New York, NY 10017
 *
 * +1 800 SOS UNIX
 * <sos-info@soscorp.com>
 *
 * --Copyright Released Product--
 */

/*
 * DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER
 * DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER
 * DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER
 *
 * SOS did not develop sos_sendmail_arpadate.  It was taken
 * from sendmail verion 8.6.9.  The copyright near that function
 * describes the restrictions that routine has.
 *
 * DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER
 * DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER
 * DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER DISCLAIMER
 */

/*
 * Everything dealing with time
 */

#include "sos.h"

#define SECONDSINDAY 86400


/* Return days since the epoch (or more generally, number of days in seconds */
time_t 
sos_days(time_t secs)
{
  if (!secs)
    secs = time(NULL);

  return (secs / SECONDSINDAY);
}


/* Return date from days */
char *
sos_daydate(time_t days, char *buf, int blen)
{
  static char stat_buf[16];
  struct tm *tm;
  time_t seconds;

  if (!buf && blen < 1)
    {
      buf = stat_buf;
      blen = 16;
    }

  if (!buf || blen < 11)
    return (NULL);

  seconds = days * SECONDSINDAY;

  tm = gmtime(&seconds);	/* Should this be localtime? */

  strftime(buf, blen, "%m/%d/%Y", tm);

  return (buf);
}


/* Return day from date */
time_t 
sos_dateday(char *buf, int blen)
{
  struct tm tm;
  char *tmp, *oldTZ;
  int epoch;

  /* Save the current time zone */
  tmp = SOS_ENV_GWD("TZ","localtime");
  if (!(oldTZ = (char *)malloc(strlen(tmp) + 4)))
    return (-1);
  strcpy(oldTZ, "TZ=");
  strcat(oldTZ, tmp);

  /* Set the time zone to GMT */
  putenv("TZ=GMT");
  tzset();

  sscanf(buf, "%d/%d/%d", &(tm.tm_mon), &(tm.tm_mday), &(tm.tm_year));
  if (tm.tm_year > 1900)
    tm.tm_year -= 1900;
  tm.tm_mon--;			/* 0-11, not 1-12 */
  tm.tm_sec = 0;
  tm.tm_wday = 0;
  tm.tm_yday = 0;
  tm.tm_isdst = 0;

  epoch = mktime(&tm);
  epoch /= 86400;

  putenv(oldTZ);
  tzset();
  return (epoch);
}


/* Return the current time suitable for prompts (like ctime) */
char *
sos_prompttime(char *buf, int blen)
{
  static char stat_buf[38];
  struct tm *tm;
  time_t seconds;

  if (!buf && blen < 1)
    {
      buf = stat_buf;
      blen = 38;
    }

  if (!buf || blen < 32)
    return (NULL);

  seconds = time(NULL);

  tm = localtime(&seconds);	/* Should this be fmtime? */

  strftime(buf, blen, "%a %b %e %H:%M:%S %Z %Y", tm);

  return (buf);
}



/*
 * Copyright (c) 1983 Eric P. Allman
 * Copyright (c) 1988, 1993
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * **  ARPADATE -- Create date in ARPANET format
 * **
 * **      Parameters:
 * **              ud -- unix style date string.  if NULL, one is created.
 * **
 * **      Returns:
 * **              pointer to an ARPANET date field
 * **
 * **      Side Effects:
 * **              none
 * **
 * **      WARNING:
 * **              date is stored in a local buffer -- subsequent
 * **              calls will overwrite.
 * **
 * **      Bugs:
 * **              Timezone is computed from local time, rather than
 * **              from whereever (and whenever) the message was sent.
 * **              To do better is very hard.
 * **
 * **              Some sites are now inserting the timezone into the
 * **              local date.  This routine should figure out what
 * **              the format is and work appropriately.
 */

char *
sos_sendmail_arpadate(ud)
     register char *ud;
{
  register char *p;
  register char *q;
  register int off;
  register int i;
  register struct tm *lt;
  time_t t;
  struct tm gmt;
  static char b[40];

  /*
   * **  Get current time.
   * **      This will be used if a null argument is passed and
   * **      to resolve the timezone.
   */

  (void)time(&t);
  if (ud == NULL)
    ud = ctime(&t);

  /*
   * **  Crack the UNIX date line in a singularly unoriginal way.
   */

  q = b;

  p = &ud[0];			/* Mon */
  *q++ = *p++;
  *q++ = *p++;
  *q++ = *p++;
  *q++ = ',';
  *q++ = ' ';

  p = &ud[8];			/* 16 */
  if (*p == ' ')
    p++;
  else
    *q++ = *p++;
  *q++ = *p++;
  *q++ = ' ';

  p = &ud[4];			/* Sep */
  *q++ = *p++;
  *q++ = *p++;
  *q++ = *p++;
  *q++ = ' ';

  p = &ud[20];			/* 1979 */
  *q++ = *p++;
  *q++ = *p++;
  *q++ = *p++;
  *q++ = *p++;
  *q++ = ' ';

  p = &ud[11];			/* 01:03:52 */
  for (i = 8; i > 0; i--)
    *q++ = *p++;

  /*
   * should really get the timezone from the time in "ud" (which
   * is only different if a non-null arg was passed which is different
   * from the current time), but for all practical purposes, returning
   * the current local zone will do (its all that is ever needed).
   */
  gmt = *gmtime(&t);
  lt = localtime(&t);

  off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;

  /* assume that offset isn't more than a day ... */
  if (lt->tm_year < gmt.tm_year)
    off -= 24 * 60;
  else if (lt->tm_year > gmt.tm_year)
    off += 24 * 60;
  else if (lt->tm_yday < gmt.tm_yday)
    off -= 24 * 60;
  else if (lt->tm_yday > gmt.tm_yday)
    off += 24 * 60;

  *q++ = ' ';
  if (off == 0)
    {
      *q++ = 'G';
      *q++ = 'M';
      *q++ = 'T';
    }
  else
    {
      if (off < 0)
	{
	  off = -off;
	  *q++ = '-';
	}
      else
	*q++ = '+';

      if (off >= 24 * 60)	/* should be impossible */
	off = 23 * 60 + 59;	/* if not, insert silly value */

      *q++ = (off / 600) + '0';
      *q++ = (off / 60) % 10 + '0';
      off %= 60;
      *q++ = (off / 10) + '0';
      *q++ = (off % 10) + '0';
    }
  *q = '\0';

  return (b);
}
