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