arpadate.c revision 77349
138032Speter/* 277349Sgshapiro * Copyright (c) 1998, 1999, 2001 Sendmail, 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 1438032Speter#ifndef lint 1577349Sgshapirostatic char id[] = "@(#)$Id: arpadate.c,v 8.23.20.2 2001/05/07 22:07:26 gshapiro Exp $"; 1664562Sgshapiro#endif /* ! lint */ 1738032Speter 1864562Sgshapiro#include <sendmail.h> 1938032Speter 2038032Speter/* 2138032Speter** ARPADATE -- Create date in ARPANET format 2238032Speter** 2338032Speter** Parameters: 2438032Speter** ud -- unix style date string. if NULL, one is created. 2538032Speter** 2638032Speter** Returns: 2738032Speter** pointer to an ARPANET date field 2838032Speter** 2938032Speter** Side Effects: 3038032Speter** none 3138032Speter** 3238032Speter** WARNING: 3338032Speter** date is stored in a local buffer -- subsequent 3438032Speter** calls will overwrite. 3538032Speter** 3638032Speter** Bugs: 3738032Speter** Timezone is computed from local time, rather than 3864562Sgshapiro** from wherever (and whenever) the message was sent. 3938032Speter** To do better is very hard. 4038032Speter** 4138032Speter** Some sites are now inserting the timezone into the 4238032Speter** local date. This routine should figure out what 4338032Speter** the format is and work appropriately. 4438032Speter*/ 4538032Speter 4638032Speter#ifndef TZNAME_MAX 4738032Speter# define TZNAME_MAX 50 /* max size of timezone */ 4864562Sgshapiro#endif /* ! TZNAME_MAX */ 4938032Speter 5038032Speter/* values for TZ_TYPE */ 5138032Speter#define TZ_NONE 0 /* no character timezone support */ 5238032Speter#define TZ_TM_NAME 1 /* use tm->tm_name */ 5338032Speter#define TZ_TM_ZONE 2 /* use tm->tm_zone */ 5438032Speter#define TZ_TZNAME 3 /* use tzname[] */ 5538032Speter#define TZ_TIMEZONE 4 /* use timezone() */ 5638032Speter 5738032Speterchar * 5838032Speterarpadate(ud) 5938032Speter register char *ud; 6038032Speter{ 6138032Speter register char *p; 6238032Speter register char *q; 6338032Speter register int off; 6438032Speter register int i; 6538032Speter register struct tm *lt; 6638032Speter time_t t; 6738032Speter struct tm gmt; 6838032Speter char *tz; 6938032Speter static char b[43 + TZNAME_MAX]; 7038032Speter 7138032Speter /* 7238032Speter ** Get current time. 7338032Speter ** This will be used if a null argument is passed and 7438032Speter ** to resolve the timezone. 7538032Speter */ 7638032Speter 7743730Speter t = curtime(); 7838032Speter if (ud == NULL) 7938032Speter ud = ctime(&t); 8038032Speter 8138032Speter /* 8238032Speter ** Crack the UNIX date line in a singularly unoriginal way. 8338032Speter */ 8438032Speter 8538032Speter q = b; 8638032Speter 8738032Speter p = &ud[0]; /* Mon */ 8838032Speter *q++ = *p++; 8938032Speter *q++ = *p++; 9038032Speter *q++ = *p++; 9138032Speter *q++ = ','; 9238032Speter *q++ = ' '; 9338032Speter 9438032Speter p = &ud[8]; /* 16 */ 9538032Speter if (*p == ' ') 9638032Speter p++; 9738032Speter else 9838032Speter *q++ = *p++; 9938032Speter *q++ = *p++; 10038032Speter *q++ = ' '; 10138032Speter 10238032Speter p = &ud[4]; /* Sep */ 10338032Speter *q++ = *p++; 10438032Speter *q++ = *p++; 10538032Speter *q++ = *p++; 10638032Speter *q++ = ' '; 10738032Speter 10838032Speter p = &ud[20]; /* 1979 */ 10938032Speter *q++ = *p++; 11038032Speter *q++ = *p++; 11138032Speter *q++ = *p++; 11238032Speter *q++ = *p++; 11338032Speter *q++ = ' '; 11438032Speter 11538032Speter p = &ud[11]; /* 01:03:52 */ 11638032Speter for (i = 8; i > 0; i--) 11738032Speter *q++ = *p++; 11838032Speter 11938032Speter /* 12077349Sgshapiro ** should really get the timezone from the time in "ud" (which 12177349Sgshapiro ** is only different if a non-null arg was passed which is different 12277349Sgshapiro ** from the current time), but for all practical purposes, returning 12377349Sgshapiro ** the current local zone will do (its all that is ever needed). 12477349Sgshapiro */ 12577349Sgshapiro 12638032Speter gmt = *gmtime(&t); 12738032Speter lt = localtime(&t); 12838032Speter 12938032Speter off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 13038032Speter 13138032Speter /* assume that offset isn't more than a day ... */ 13238032Speter if (lt->tm_year < gmt.tm_year) 13338032Speter off -= 24 * 60; 13438032Speter else if (lt->tm_year > gmt.tm_year) 13538032Speter off += 24 * 60; 13638032Speter else if (lt->tm_yday < gmt.tm_yday) 13738032Speter off -= 24 * 60; 13838032Speter else if (lt->tm_yday > gmt.tm_yday) 13938032Speter off += 24 * 60; 14038032Speter 14138032Speter *q++ = ' '; 14238032Speter if (off == 0) 14338032Speter { 14438032Speter *q++ = 'G'; 14538032Speter *q++ = 'M'; 14638032Speter *q++ = 'T'; 14738032Speter } 14838032Speter else 14938032Speter { 15038032Speter tz = NULL; 15138032Speter#if TZ_TYPE == TZ_TM_NAME 15238032Speter tz = lt->tm_name; 15364562Sgshapiro#endif /* TZ_TYPE == TZ_TM_NAME */ 15438032Speter#if TZ_TYPE == TZ_TM_ZONE 15538032Speter tz = lt->tm_zone; 15664562Sgshapiro#endif /* TZ_TYPE == TZ_TM_ZONE */ 15738032Speter#if TZ_TYPE == TZ_TZNAME 15838032Speter { 15938032Speter extern char *tzname[]; 16038032Speter 16143730Speter if (lt->tm_isdst > 0) 16243730Speter tz = tzname[1]; 16343730Speter else if (lt->tm_isdst == 0) 16443730Speter tz = tzname[0]; 16543730Speter else 16643730Speter tz = NULL; 16738032Speter } 16864562Sgshapiro#endif /* TZ_TYPE == TZ_TZNAME */ 16938032Speter#if TZ_TYPE == TZ_TIMEZONE 17038032Speter { 17138032Speter extern char *timezone(); 17238032Speter 17338032Speter tz = timezone(off, lt->tm_isdst); 17438032Speter } 17564562Sgshapiro#endif /* TZ_TYPE == TZ_TIMEZONE */ 17638032Speter if (off < 0) 17738032Speter { 17838032Speter off = -off; 17938032Speter *q++ = '-'; 18038032Speter } 18138032Speter else 18238032Speter *q++ = '+'; 18338032Speter 18438032Speter if (off >= 24*60) /* should be impossible */ 18538032Speter off = 23*60+59; /* if not, insert silly value */ 18638032Speter 18738032Speter *q++ = (off / 600) + '0'; 18838032Speter *q++ = (off / 60) % 10 + '0'; 18938032Speter off %= 60; 19038032Speter *q++ = (off / 10) + '0'; 19138032Speter *q++ = (off % 10) + '0'; 19238032Speter if (tz != NULL && *tz != '\0') 19338032Speter { 19438032Speter *q++ = ' '; 19538032Speter *q++ = '('; 19638032Speter while (*tz != '\0' && q < &b[sizeof b - 3]) 19738032Speter *q++ = *tz++; 19838032Speter *q++ = ')'; 19938032Speter } 20038032Speter } 20138032Speter *q = '\0'; 20238032Speter 20364562Sgshapiro return b; 20438032Speter} 205