| 1 | /* |
| 2 | * Copyright (c) 1983 Eric P. Allman |
| 3 | * Copyright (c) 1988, 1993 |
| 4 | * The Regents of the University of California. All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * 3. All advertising materials mentioning features or use of this software |
| 15 | * must display the following acknowledgement: |
| 16 | * This product includes software developed by the University of |
| 17 | * California, Berkeley and its contributors. |
| 18 | * 4. Neither the name of the University nor the names of its contributors |
| 19 | * may be used to endorse or promote products derived from this software |
| 20 | * without specific prior written permission. |
| 21 | * |
| 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 32 | * SUCH DAMAGE. |
| 33 | */ |
| 34 | |
| 35 | #ifndef lint |
| 36 | static char sccsid[] = "@(#)arpadate.c 8.1 (Berkeley) 6/7/93"; |
| 37 | #endif /* not lint */ |
| 38 | |
| 39 | # include "sendmail.h" |
| 40 | |
| 41 | /* |
| 42 | ** ARPADATE -- Create date in ARPANET format |
| 43 | ** |
| 44 | ** Parameters: |
| 45 | ** ud -- unix style date string. if NULL, one is created. |
| 46 | ** |
| 47 | ** Returns: |
| 48 | ** pointer to an ARPANET date field |
| 49 | ** |
| 50 | ** Side Effects: |
| 51 | ** none |
| 52 | ** |
| 53 | ** WARNING: |
| 54 | ** date is stored in a local buffer -- subsequent |
| 55 | ** calls will overwrite. |
| 56 | ** |
| 57 | ** Bugs: |
| 58 | ** Timezone is computed from local time, rather than |
| 59 | ** from whereever (and whenever) the message was sent. |
| 60 | ** To do better is very hard. |
| 61 | ** |
| 62 | ** Some sites are now inserting the timezone into the |
| 63 | ** local date. This routine should figure out what |
| 64 | ** the format is and work appropriately. |
| 65 | */ |
| 66 | |
| 67 | char * |
| 68 | arpadate(ud) |
| 69 | register char *ud; |
| 70 | { |
| 71 | register char *p; |
| 72 | register char *q; |
| 73 | register int off; |
| 74 | register int i; |
| 75 | register struct tm *lt; |
| 76 | time_t t; |
| 77 | struct tm gmt; |
| 78 | static char b[40]; |
| 79 | |
| 80 | /* |
| 81 | ** Get current time. |
| 82 | ** This will be used if a null argument is passed and |
| 83 | ** to resolve the timezone. |
| 84 | */ |
| 85 | |
| 86 | (void) time(&t); |
| 87 | if (ud == NULL) |
| 88 | ud = ctime(&t); |
| 89 | |
| 90 | /* |
| 91 | ** Crack the UNIX date line in a singularly unoriginal way. |
| 92 | */ |
| 93 | |
| 94 | q = b; |
| 95 | |
| 96 | p = &ud[0]; /* Mon */ |
| 97 | *q++ = *p++; |
| 98 | *q++ = *p++; |
| 99 | *q++ = *p++; |
| 100 | *q++ = ','; |
| 101 | *q++ = ' '; |
| 102 | |
| 103 | p = &ud[8]; /* 16 */ |
| 104 | if (*p == ' ') |
| 105 | p++; |
| 106 | else |
| 107 | *q++ = *p++; |
| 108 | *q++ = *p++; |
| 109 | *q++ = ' '; |
| 110 | |
| 111 | p = &ud[4]; /* Sep */ |
| 112 | *q++ = *p++; |
| 113 | *q++ = *p++; |
| 114 | *q++ = *p++; |
| 115 | *q++ = ' '; |
| 116 | |
| 117 | p = &ud[20]; /* 1979 */ |
| 118 | *q++ = *p++; |
| 119 | *q++ = *p++; |
| 120 | *q++ = *p++; |
| 121 | *q++ = *p++; |
| 122 | *q++ = ' '; |
| 123 | |
| 124 | p = &ud[11]; /* 01:03:52 */ |
| 125 | for (i = 8; i > 0; i--) |
| 126 | *q++ = *p++; |
| 127 | |
| 128 | /* |
| 129 | * should really get the timezone from the time in "ud" (which |
| 130 | * is only different if a non-null arg was passed which is different |
| 131 | * from the current time), but for all practical purposes, returning |
| 132 | * the current local zone will do (its all that is ever needed). |
| 133 | */ |
| 134 | gmt = *gmtime(&t); |
| 135 | lt = localtime(&t); |
| 136 | |
| 137 | off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; |
| 138 | |
| 139 | /* assume that offset isn't more than a day ... */ |
| 140 | if (lt->tm_year < gmt.tm_year) |
| 141 | off -= 24 * 60; |
| 142 | else if (lt->tm_year > gmt.tm_year) |
| 143 | off += 24 * 60; |
| 144 | else if (lt->tm_yday < gmt.tm_yday) |
| 145 | off -= 24 * 60; |
| 146 | else if (lt->tm_yday > gmt.tm_yday) |
| 147 | off += 24 * 60; |
| 148 | |
| 149 | *q++ = ' '; |
| 150 | if (off == 0) { |
| 151 | *q++ = 'G'; |
| 152 | *q++ = 'M'; |
| 153 | *q++ = 'T'; |
| 154 | } else { |
| 155 | if (off < 0) { |
| 156 | off = -off; |
| 157 | *q++ = '-'; |
| 158 | } else |
| 159 | *q++ = '+'; |
| 160 | |
| 161 | if (off >= 24*60) /* should be impossible */ |
| 162 | off = 23*60+59; /* if not, insert silly value */ |
| 163 | |
| 164 | *q++ = (off / 600) + '0'; |
| 165 | *q++ = (off / 60) % 10 + '0'; |
| 166 | off %= 60; |
| 167 | *q++ = (off / 10) + '0'; |
| 168 | *q++ = (off % 10) + '0'; |
| 169 | } |
| 170 | *q = '\0'; |
| 171 | |
| 172 | return (b); |
| 173 | } |