1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)arpadate.c 6.7 (Berkeley) 02/21/93"; 11 #endif /* not lint */ 12 13 # include "sendmail.h" 14 # include <sys/types.h> 15 16 /* 17 ** ARPADATE -- Create date in ARPANET format 18 ** 19 ** Parameters: 20 ** ud -- unix style date string. if NULL, one is created. 21 ** 22 ** Returns: 23 ** pointer to an ARPANET date field 24 ** 25 ** Side Effects: 26 ** none 27 ** 28 ** WARNING: 29 ** date is stored in a local buffer -- subsequent 30 ** calls will overwrite. 31 ** 32 ** Bugs: 33 ** Timezone is computed from local time, rather than 34 ** from whereever (and whenever) the message was sent. 35 ** To do better is very hard. 36 ** 37 ** Some sites are now inserting the timezone into the 38 ** local date. This routine should figure out what 39 ** the format is and work appropriately. 40 */ 41 42 char * 43 arpadate(ud) 44 register char *ud; 45 { 46 register char *p; 47 register char *q; 48 register int off; 49 register int i; 50 register struct tm *lt; 51 time_t t; 52 struct tm gmt; 53 static char b[40]; 54 55 /* 56 ** Get current time. 57 ** This will be used if a null argument is passed and 58 ** to resolve the timezone. 59 */ 60 61 (void) time(&t); 62 if (ud == NULL) 63 ud = ctime(&t); 64 65 /* 66 ** Crack the UNIX date line in a singularly unoriginal way. 67 */ 68 69 q = b; 70 71 p = &ud[0]; /* Mon */ 72 *q++ = *p++; 73 *q++ = *p++; 74 *q++ = *p++; 75 *q++ = ','; 76 *q++ = ' '; 77 78 p = &ud[8]; /* 16 */ 79 if (*p == ' ') 80 p++; 81 else 82 *q++ = *p++; 83 *q++ = *p++; 84 *q++ = ' '; 85 86 p = &ud[4]; /* Sep */ 87 *q++ = *p++; 88 *q++ = *p++; 89 *q++ = *p++; 90 *q++ = ' '; 91 92 p = &ud[20]; /* 1979 */ 93 *q++ = *p++; 94 *q++ = *p++; 95 *q++ = *p++; 96 *q++ = *p++; 97 *q++ = ' '; 98 99 p = &ud[11]; /* 01:03:52 */ 100 for (i = 8; i > 0; i--) 101 *q++ = *p++; 102 103 /* 104 * should really get the timezone from the time in "ud" (which 105 * is only different if a non-null arg was passed which is different 106 * from the current time), but for all practical purposes, returning 107 * the current local zone will do (its all that is ever needed). 108 */ 109 gmt = *gmtime(&t); 110 lt = localtime(&t); 111 112 off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 113 114 /* assume that offset isn't more than a day ... */ 115 if (lt->tm_year < gmt.tm_year) 116 off -= 24 * 60; 117 else if (lt->tm_year > gmt.tm_year) 118 off += 24 * 60; 119 else if (lt->tm_yday < gmt.tm_yday) 120 off -= 24 * 60; 121 else if (lt->tm_yday > gmt.tm_yday) 122 off += 24 * 60; 123 124 *q++ = ' '; 125 if (off == 0) { 126 *q++ = 'G'; 127 *q++ = 'M'; 128 *q++ = 'T'; 129 } else { 130 if (off < 0) { 131 off = -off; 132 *q++ = '-'; 133 } else 134 *q++ = '+'; 135 136 if (off >= 24*60) /* should be impossible */ 137 off = 23*60+59; /* if not, insert silly value */ 138 139 *q++ = (off / 600) + '0'; 140 *q++ = (off / 60) % 10 + '0'; 141 off %= 60; 142 *q++ = (off / 10) + '0'; 143 *q++ = (off % 10) + '0'; 144 } 145 *q = '\0'; 146 147 return (b); 148 } 149 150 /* 151 ** NEXTATOM -- Return pointer to next atom in header 152 ** (skip whitespace and comments) 153 ** 154 ** Parameters: 155 ** s -- pointer to header string 156 ** 157 ** Returns: 158 ** pointer advanced to next non-comment header atom 159 ** 160 ** Side Effects: 161 ** none 162 */ 163 164 static char * 165 nextatom(s) 166 char *s; 167 { 168 char *p; 169 170 for (p = s; 171 *p && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '('); 172 p++) 173 { 174 if (*p == '(') 175 { 176 int nested = 0; 177 178 /* ignore comments */ 179 p++; 180 for (; *p; p++) 181 { 182 if (*p == '(') 183 nested++; 184 else if (*p == ')') 185 if (!nested) 186 break; 187 else 188 nested--; 189 } 190 } 191 } 192 return (p); 193 } 194