138032Speter/* 2261194Sgshapiro * Copyright (c) 1998-2001 Proofpoint, Inc. and its suppliers. 364562Sgshapiro * All rights reserved. 438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 538032Speter * Copyright (c) 1988, 1993 638032Speter * The Regents of the University of California. All rights reserved. 738032Speter * 838032Speter * By using this file, you agree to the terms and conditions set 938032Speter * forth in the LICENSE file which can be found at the top level of 1038032Speter * the sendmail distribution. 1138032Speter * 1238032Speter */ 1338032Speter 1464562Sgshapiro#include <sendmail.h> 1538032Speter 16266527SgshapiroSM_RCSID("@(#)$Id: arpadate.c,v 8.32 2013-11-22 20:51:55 ca Exp $") 1790792Sgshapiro 1838032Speter/* 1938032Speter** ARPADATE -- Create date in ARPANET format 2038032Speter** 2138032Speter** Parameters: 2238032Speter** ud -- unix style date string. if NULL, one is created. 2338032Speter** 2438032Speter** Returns: 2538032Speter** pointer to an ARPANET date field 2638032Speter** 2738032Speter** Side Effects: 2838032Speter** none 2938032Speter** 3038032Speter** WARNING: 3138032Speter** date is stored in a local buffer -- subsequent 3238032Speter** calls will overwrite. 3338032Speter** 3438032Speter** Bugs: 3538032Speter** Timezone is computed from local time, rather than 3664562Sgshapiro** from wherever (and whenever) the message was sent. 3738032Speter** To do better is very hard. 3838032Speter** 3938032Speter** Some sites are now inserting the timezone into the 4038032Speter** local date. This routine should figure out what 4138032Speter** the format is and work appropriately. 4238032Speter*/ 4338032Speter 4438032Speter#ifndef TZNAME_MAX 4538032Speter# define TZNAME_MAX 50 /* max size of timezone */ 46363466Sgshapiro#endif 4738032Speter 4838032Speter/* values for TZ_TYPE */ 4938032Speter#define TZ_NONE 0 /* no character timezone support */ 5038032Speter#define TZ_TM_NAME 1 /* use tm->tm_name */ 5138032Speter#define TZ_TM_ZONE 2 /* use tm->tm_zone */ 5238032Speter#define TZ_TZNAME 3 /* use tzname[] */ 5338032Speter#define TZ_TIMEZONE 4 /* use timezone() */ 5438032Speter 5538032Speterchar * 5638032Speterarpadate(ud) 5738032Speter register char *ud; 5838032Speter{ 5938032Speter register char *p; 6038032Speter register char *q; 6138032Speter register int off; 6238032Speter register int i; 6338032Speter register struct tm *lt; 6438032Speter time_t t; 6538032Speter struct tm gmt; 6638032Speter char *tz; 6738032Speter static char b[43 + TZNAME_MAX]; 6838032Speter 6938032Speter /* 7038032Speter ** Get current time. 7138032Speter ** This will be used if a null argument is passed and 7238032Speter ** to resolve the timezone. 7338032Speter */ 7438032Speter 7590792Sgshapiro /* SM_REQUIRE(ud == NULL || strlen(ud) >= 23); */ 7643730Speter t = curtime(); 7738032Speter if (ud == NULL) 7838032Speter ud = ctime(&t); 7938032Speter 8038032Speter /* 8138032Speter ** Crack the UNIX date line in a singularly unoriginal way. 8238032Speter */ 8338032Speter 8438032Speter q = b; 8538032Speter 8638032Speter p = &ud[0]; /* Mon */ 8738032Speter *q++ = *p++; 8838032Speter *q++ = *p++; 8938032Speter *q++ = *p++; 9038032Speter *q++ = ','; 9138032Speter *q++ = ' '; 9238032Speter 9338032Speter p = &ud[8]; /* 16 */ 9438032Speter if (*p == ' ') 9538032Speter p++; 9638032Speter else 9738032Speter *q++ = *p++; 9838032Speter *q++ = *p++; 9938032Speter *q++ = ' '; 10038032Speter 10138032Speter p = &ud[4]; /* Sep */ 10238032Speter *q++ = *p++; 10338032Speter *q++ = *p++; 10438032Speter *q++ = *p++; 10538032Speter *q++ = ' '; 10638032Speter 10738032Speter p = &ud[20]; /* 1979 */ 10838032Speter *q++ = *p++; 10938032Speter *q++ = *p++; 11038032Speter *q++ = *p++; 11138032Speter *q++ = *p++; 11238032Speter *q++ = ' '; 11338032Speter 11438032Speter p = &ud[11]; /* 01:03:52 */ 11538032Speter for (i = 8; i > 0; i--) 11638032Speter *q++ = *p++; 11738032Speter 11838032Speter /* 11977349Sgshapiro ** should really get the timezone from the time in "ud" (which 12077349Sgshapiro ** is only different if a non-null arg was passed which is different 12177349Sgshapiro ** from the current time), but for all practical purposes, returning 12277349Sgshapiro ** the current local zone will do (its all that is ever needed). 12377349Sgshapiro */ 12477349Sgshapiro 12538032Speter gmt = *gmtime(&t); 12638032Speter lt = localtime(&t); 12738032Speter 12838032Speter off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 12938032Speter 13038032Speter /* assume that offset isn't more than a day ... */ 13138032Speter if (lt->tm_year < gmt.tm_year) 13238032Speter off -= 24 * 60; 13338032Speter else if (lt->tm_year > gmt.tm_year) 13438032Speter off += 24 * 60; 13538032Speter else if (lt->tm_yday < gmt.tm_yday) 13638032Speter off -= 24 * 60; 13738032Speter else if (lt->tm_yday > gmt.tm_yday) 13838032Speter off += 24 * 60; 13938032Speter 14038032Speter *q++ = ' '; 14138032Speter if (off == 0) 14238032Speter { 14338032Speter *q++ = 'G'; 14438032Speter *q++ = 'M'; 14538032Speter *q++ = 'T'; 14638032Speter } 14738032Speter else 14838032Speter { 14938032Speter tz = NULL; 15038032Speter#if TZ_TYPE == TZ_TM_NAME 15138032Speter tz = lt->tm_name; 152363466Sgshapiro#endif 15338032Speter#if TZ_TYPE == TZ_TM_ZONE 15438032Speter tz = lt->tm_zone; 155363466Sgshapiro#endif 15638032Speter#if TZ_TYPE == TZ_TZNAME 15738032Speter { 15838032Speter extern char *tzname[]; 15938032Speter 16043730Speter if (lt->tm_isdst > 0) 16143730Speter tz = tzname[1]; 16243730Speter else if (lt->tm_isdst == 0) 16343730Speter tz = tzname[0]; 16443730Speter else 16543730Speter tz = NULL; 16638032Speter } 16764562Sgshapiro#endif /* TZ_TYPE == TZ_TZNAME */ 16838032Speter#if TZ_TYPE == TZ_TIMEZONE 16938032Speter { 17038032Speter extern char *timezone(); 17138032Speter 17238032Speter tz = timezone(off, lt->tm_isdst); 17338032Speter } 17464562Sgshapiro#endif /* TZ_TYPE == TZ_TIMEZONE */ 17538032Speter if (off < 0) 17638032Speter { 17738032Speter off = -off; 17838032Speter *q++ = '-'; 17938032Speter } 18038032Speter else 18138032Speter *q++ = '+'; 18238032Speter 18338032Speter if (off >= 24*60) /* should be impossible */ 18438032Speter off = 23*60+59; /* if not, insert silly value */ 18538032Speter 18638032Speter *q++ = (off / 600) + '0'; 18738032Speter *q++ = (off / 60) % 10 + '0'; 18838032Speter off %= 60; 18938032Speter *q++ = (off / 10) + '0'; 19038032Speter *q++ = (off % 10) + '0'; 19138032Speter if (tz != NULL && *tz != '\0') 19238032Speter { 19338032Speter *q++ = ' '; 19438032Speter *q++ = '('; 195168515Sgshapiro while (*tz != '\0' && q < &b[sizeof(b) - 3]) 19638032Speter *q++ = *tz++; 19738032Speter *q++ = ')'; 19838032Speter } 19938032Speter } 20038032Speter *q = '\0'; 20138032Speter 20264562Sgshapiro return b; 20338032Speter} 204