1: /* 2: * Copyright (c) 1989, 1993 3: * The Regents of the University of California. All rights reserved. 4: * 5: * Redistribution and use in source and binary forms, with or without 6: * modification, are permitted provided that the following conditions 7: * are met: 8: * 1. Redistributions of source code must retain the above copyright 9: * notice, this list of conditions and the following disclaimer. 10: * 2. Redistributions in binary form must reproduce the above copyright 11: * notice, this list of conditions and the following disclaimer in the 12: * documentation and/or other materials provided with the distribution. 13: * 3. All advertising materials mentioning features or use of this software 14: * must display the following acknowledgement: 15: * This product includes software developed by the University of 16: * California, Berkeley and its contributors. 17: * 4. Neither the name of the University nor the names of its contributors 18: * may be used to endorse or promote products derived from this software 19: * without specific prior written permission. 20: * 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31: * SUCH DAMAGE. 32: */ 33: 34: #if defined(LIBC_SCCS) && !defined(lint) 35: static char sccsid[] = "@(#)strftime.c 8.1.1 (2.11BSD) 1995/04/01"; 36: #endif /* LIBC_SCCS and not lint */ 37: 38: #include <sys/types.h> 39: #include <sys/time.h> 40: #include <tzfile.h> 41: #include <string.h> 42: 43: static char *Afmt[] = { 44: "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 45: "Saturday", 46: }; 47: static char *Bfmt[] = { 48: "January", "February", "March", "April", "May", "June", "July", 49: "August", "September", "October", "November", "December", 50: }; 51: 52: static size_t gsize; 53: static char *pt; 54: static int _add(); 55: static int _conv(); 56: static size_t _fmt(); 57: 58: size_t 59: strftime(s, maxsize, format, t) 60: char *s; 61: size_t maxsize; 62: char *format; 63: struct tm *t; 64: { 65: 66: pt = s; 67: if ((gsize = maxsize) < 1) 68: return(0); 69: if (_fmt(format, t)) { 70: *pt = '\0'; 71: return(maxsize - gsize); 72: } 73: return(0); 74: } 75: 76: static size_t 77: _fmt(format, t) 78: register char *format; 79: register struct tm *t; 80: { 81: char ch, *cp, junk[4]; 82: 83: for (; *format; ++format) { 84: if (*format == '%') 85: switch(ch = *++format) { 86: case '\0': 87: --format; 88: break; 89: case 'A': 90: case 'a': 91: if (t->tm_wday < 0 || t->tm_wday > 6) 92: return(0); 93: if (ch == 'a') 94: { 95: bcopy(Afmt[t->tm_wday], junk, 3); 96: junk[3] = '\0'; 97: cp = junk; 98: } 99: else 100: cp = Afmt[t->tm_wday]; 101: if (!_add(cp)) 102: return(0); 103: continue; 104: case 'B': 105: case 'b': 106: case 'h': 107: if (t->tm_mon < 0 || t->tm_mon > 11) 108: return(0); 109: if (ch == 'b') 110: { 111: bcopy(Bfmt[t->tm_mon], junk, 3); 112: junk[3] = '\0'; 113: cp = junk; 114: } 115: else 116: cp = Bfmt[t->tm_mon]; 117: if (!_add(cp)) 118: return(0); 119: continue; 120: case 'C': 121: if (!_fmt("%a %b %e %H:%M:%S %Y", t)) 122: return(0); 123: continue; 124: case 'c': 125: if (!_fmt("%m/%d/%y %H:%M:%S", t)) 126: return(0); 127: continue; 128: case 'D': 129: if (!_fmt("%m/%d/%y", t)) 130: return(0); 131: continue; 132: case 'd': 133: if (!_conv(t->tm_mday, 2, '0')) 134: return(0); 135: continue; 136: case 'e': 137: if (!_conv(t->tm_mday, 2, ' ')) 138: return(0); 139: continue; 140: case 'H': 141: if (!_conv(t->tm_hour, 2, '0')) 142: return(0); 143: continue; 144: case 'I': 145: if (!_conv(t->tm_hour % 12 ? 146: t->tm_hour % 12 : 12, 2, '0')) 147: return(0); 148: continue; 149: case 'j': 150: if (!_conv(t->tm_yday + 1, 3, '0')) 151: return(0); 152: continue; 153: case 'k': 154: if (!_conv(t->tm_hour, 2, ' ')) 155: return(0); 156: continue; 157: case 'l': 158: if (!_conv(t->tm_hour % 12 ? 159: t->tm_hour % 12 : 12, 2, ' ')) 160: return(0); 161: continue; 162: case 'M': 163: if (!_conv(t->tm_min, 2, '0')) 164: return(0); 165: continue; 166: case 'm': 167: if (!_conv(t->tm_mon + 1, 2, '0')) 168: return(0); 169: continue; 170: case 'n': 171: if (!_add("\n")) 172: return(0); 173: continue; 174: case 'p': 175: if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) 176: return(0); 177: continue; 178: case 'R': 179: if (!_fmt("%H:%M", t)) 180: return(0); 181: continue; 182: case 'r': 183: if (!_fmt("%I:%M:%S %p", t)) 184: return(0); 185: continue; 186: case 'S': 187: if (!_conv(t->tm_sec, 2, '0')) 188: return(0); 189: continue; 190: case 'T': 191: case 'X': 192: if (!_fmt("%H:%M:%S", t)) 193: return(0); 194: continue; 195: case 't': 196: if (!_add("\t")) 197: return(0); 198: continue; 199: case 'U': 200: if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, 201: 2, '0')) 202: return(0); 203: continue; 204: case 'W': 205: if (!_conv((t->tm_yday + 7 - 206: (t->tm_wday ? (t->tm_wday - 1) : 6)) 207: / 7, 2, '0')) 208: return(0); 209: continue; 210: case 'w': 211: if (!_conv(t->tm_wday, 1, '0')) 212: return(0); 213: continue; 214: case 'x': 215: if (!_fmt("%m/%d/%y", t)) 216: return(0); 217: continue; 218: case 'y': 219: if (!_conv((t->tm_year + TM_YEAR_BASE) 220: % 100, 2, '0')) 221: return(0); 222: continue; 223: case 'Y': 224: if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) 225: return(0); 226: continue; 227: case 'Z': 228: if (!t->tm_zone || !_add(t->tm_zone)) 229: return(0); 230: continue; 231: case '%': 232: /* 233: * X311J/88-090 (4.12.3.5): if conversion char is 234: * undefined, behavior is undefined. Print out the 235: * character itself as printf(3) does. 236: */ 237: default: 238: break; 239: } 240: if (!gsize--) 241: return(0); 242: *pt++ = *format; 243: } 244: return(gsize); 245: } 246: 247: static int 248: _conv(n, digits, pad) 249: int n, digits, pad; 250: { 251: static char buf[10]; 252: register char *p; 253: 254: for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) 255: *p-- = n % 10 + '0'; 256: while (p > buf && digits-- > 0) 257: *p-- = pad; 258: return(_add(++p)); 259: } 260: 261: static int 262: _add(str) 263: register char *str; 264: { 265: for (;; ++pt, --gsize) { 266: if (!gsize) 267: return(0); 268: if (!(*pt = *str++)) 269: return(1); 270: } 271: }