137103Sbostic /* 237103Sbostic * Copyright (c) 1989 The Regents of the University of California. 337103Sbostic * All rights reserved. 437103Sbostic * 537103Sbostic * Redistribution and use in source and binary forms are permitted 637103Sbostic * provided that the above copyright notice and this paragraph are 737103Sbostic * duplicated in all such forms and that any documentation, 837103Sbostic * advertising materials, and other materials related to such 937103Sbostic * distribution and use acknowledge that the software was developed 1037103Sbostic * by the University of California, Berkeley. The name of the 1137103Sbostic * University may not be used to endorse or promote products derived 1237103Sbostic * from this software without specific prior written permission. 1337103Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437103Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537103Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637103Sbostic */ 1737103Sbostic 1837103Sbostic #if defined(LIBC_SCCS) && !defined(lint) 19*42181Sbostic static char sccsid[] = "@(#)strftime.c 5.7 (Berkeley) 05/17/90"; 2037103Sbostic #endif /* LIBC_SCCS and not lint */ 2137103Sbostic 2237103Sbostic #include <sys/types.h> 2337103Sbostic #include <sys/time.h> 2437103Sbostic #include <tzfile.h> 25*42181Sbostic #include <string.h> 2637103Sbostic 2737103Sbostic static char *afmt[] = { 2837103Sbostic "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 2937103Sbostic }; 3037103Sbostic static char *Afmt[] = { 3137103Sbostic "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 3237103Sbostic "Saturday", 3337103Sbostic }; 3437103Sbostic static char *bfmt[] = { 3537103Sbostic "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 3637103Sbostic "Oct", "Nov", "Dec", 3737103Sbostic }; 3837103Sbostic static char *Bfmt[] = { 3937103Sbostic "January", "February", "March", "April", "May", "June", "July", 4037103Sbostic "August", "September", "October", "November", "December", 4137103Sbostic }; 4237103Sbostic 4337103Sbostic static size_t gsize; 4437103Sbostic static char *pt; 4537103Sbostic 4637103Sbostic size_t 4737103Sbostic strftime(s, maxsize, format, t) 4837103Sbostic char *s; 4937103Sbostic char *format; 5037103Sbostic size_t maxsize; 5137103Sbostic struct tm *t; 5237103Sbostic { 5337103Sbostic size_t _fmt(); 5437103Sbostic 5537103Sbostic pt = s; 5637103Sbostic if ((gsize = maxsize) < 1) 5737103Sbostic return(0); 5837103Sbostic if (_fmt(format, t)) { 5937103Sbostic *pt = '\0'; 6037103Sbostic return(maxsize - gsize); 6137103Sbostic } 6237103Sbostic return(0); 6337103Sbostic } 6437103Sbostic 6537103Sbostic static size_t 6637103Sbostic _fmt(format, t) 6737103Sbostic register char *format; 6837103Sbostic struct tm *t; 6937103Sbostic { 7037103Sbostic for (; *format; ++format) { 7137103Sbostic if (*format == '%') 7237103Sbostic switch(*++format) { 7337176Sbostic case '\0': 7437176Sbostic --format; 7537176Sbostic break; 7637103Sbostic case 'A': 7737176Sbostic if (t->tm_wday < 0 || t->tm_wday > 6) 7837103Sbostic return(0); 7937176Sbostic if (!_add(Afmt[t->tm_wday])) 8037176Sbostic return(0); 8137103Sbostic continue; 8237103Sbostic case 'a': 8337176Sbostic if (t->tm_wday < 0 || t->tm_wday > 6) 8437103Sbostic return(0); 8537176Sbostic if (!_add(afmt[t->tm_wday])) 8637176Sbostic return(0); 8737103Sbostic continue; 8837103Sbostic case 'B': 8937176Sbostic if (t->tm_mon < 0 || t->tm_mon > 11) 9037176Sbostic return(0); 9137103Sbostic if (!_add(Bfmt[t->tm_mon])) 9237103Sbostic return(0); 9337103Sbostic continue; 9437103Sbostic case 'b': 9537137Sbostic case 'h': 9637176Sbostic if (t->tm_mon < 0 || t->tm_mon > 11) 9737176Sbostic return(0); 9837103Sbostic if (!_add(bfmt[t->tm_mon])) 9937103Sbostic return(0); 10037103Sbostic continue; 10137346Sbostic case 'C': 10237346Sbostic if (!_fmt("%a %b %e %H:%M:%S %Y", t)) 10337346Sbostic return(0); 10437346Sbostic continue; 10537103Sbostic case 'c': 10637344Sbostic if (!_fmt("%m/%d/%y %H:%M:%S", t)) 10737103Sbostic return(0); 10837103Sbostic continue; 10937346Sbostic case 'e': 11037346Sbostic if (!_conv(t->tm_mday, 2, ' ')) 11137346Sbostic return(0); 11237346Sbostic continue; 11337137Sbostic case 'D': 11437137Sbostic if (!_fmt("%m/%d/%y", t)) 11537137Sbostic return(0); 11637137Sbostic continue; 11737103Sbostic case 'd': 11837346Sbostic if (!_conv(t->tm_mday, 2, '0')) 11937103Sbostic return(0); 12037103Sbostic continue; 12137103Sbostic case 'H': 12237346Sbostic if (!_conv(t->tm_hour, 2, '0')) 12337103Sbostic return(0); 12437103Sbostic continue; 12537103Sbostic case 'I': 12637176Sbostic if (!_conv(t->tm_hour % 12 ? 12737346Sbostic t->tm_hour % 12 : 12, 2, '0')) 12837103Sbostic return(0); 12937103Sbostic continue; 13037103Sbostic case 'j': 13137346Sbostic if (!_conv(t->tm_yday + 1, 3, '0')) 13237103Sbostic return(0); 13337103Sbostic continue; 13437346Sbostic case 'k': 13537346Sbostic if (!_conv(t->tm_hour, 2, ' ')) 13637346Sbostic return(0); 13737346Sbostic continue; 13837346Sbostic case 'l': 13937346Sbostic if (!_conv(t->tm_hour % 12 ? 14037346Sbostic t->tm_hour % 12 : 12, 2, ' ')) 14137346Sbostic return(0); 14237346Sbostic continue; 14337103Sbostic case 'M': 14437346Sbostic if (!_conv(t->tm_min, 2, '0')) 14537103Sbostic return(0); 14637103Sbostic continue; 14737103Sbostic case 'm': 14837346Sbostic if (!_conv(t->tm_mon + 1, 2, '0')) 14937103Sbostic return(0); 15037103Sbostic continue; 15137137Sbostic case 'n': 15237137Sbostic if (!_add("\n")) 15337137Sbostic return(0); 15437137Sbostic continue; 15537103Sbostic case 'p': 15637176Sbostic if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) 15737103Sbostic return(0); 15837103Sbostic continue; 15937137Sbostic case 'R': 16037137Sbostic if (!_fmt("%H:%M", t)) 16137137Sbostic return(0); 16237137Sbostic continue; 16337137Sbostic case 'r': 16437137Sbostic if (!_fmt("%I:%M:%S %p", t)) 16537137Sbostic return(0); 16637137Sbostic continue; 16737103Sbostic case 'S': 16837346Sbostic if (!_conv(t->tm_sec, 2, '0')) 16937103Sbostic return(0); 17037103Sbostic continue; 17137137Sbostic case 'T': 17237137Sbostic case 'X': 17337137Sbostic if (!_fmt("%H:%M:%S", t)) 17437137Sbostic return(0); 17537137Sbostic continue; 17637137Sbostic case 't': 17737137Sbostic if (!_add("\t")) 17837137Sbostic return(0); 17937137Sbostic continue; 18037103Sbostic case 'U': 18137103Sbostic if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, 18237346Sbostic 2, '0')) 18337103Sbostic return(0); 18437103Sbostic continue; 18537103Sbostic case 'W': 18637103Sbostic if (!_conv((t->tm_yday + 7 - 18737176Sbostic (t->tm_wday ? (t->tm_wday - 1) : 6)) 18837346Sbostic / 7, 2, '0')) 18937103Sbostic return(0); 19037103Sbostic continue; 19137103Sbostic case 'w': 19237346Sbostic if (!_conv(t->tm_wday, 1, '0')) 19337103Sbostic return(0); 19437103Sbostic continue; 19537103Sbostic case 'x': 19637344Sbostic if (!_fmt("%m/%d/%y", t)) 19737103Sbostic return(0); 19837103Sbostic continue; 19937103Sbostic case 'y': 20037103Sbostic if (!_conv((t->tm_year + TM_YEAR_BASE) 20137346Sbostic % 100, 2, '0')) 20237103Sbostic return(0); 20337103Sbostic continue; 20437103Sbostic case 'Y': 20537346Sbostic if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) 20637103Sbostic return(0); 20737103Sbostic continue; 20837103Sbostic case 'Z': 20937176Sbostic if (!t->tm_zone || !_add(t->tm_zone)) 21037103Sbostic return(0); 21137103Sbostic continue; 21237103Sbostic case '%': 21337103Sbostic /* 21437103Sbostic * X311J/88-090 (4.12.3.5): if conversion char is 21537103Sbostic * undefined, behavior is undefined. Print out the 21637346Sbostic * character itself as printf(3) does. 21737103Sbostic */ 21837103Sbostic default: 21937103Sbostic break; 22037103Sbostic } 22137103Sbostic if (!gsize--) 22237103Sbostic return(0); 22337103Sbostic *pt++ = *format; 22437103Sbostic } 22537103Sbostic return(gsize); 22637103Sbostic } 22737103Sbostic 22837103Sbostic static 22937346Sbostic _conv(n, digits, pad) 23037103Sbostic int n, digits; 23137346Sbostic char pad; 23237103Sbostic { 23337103Sbostic static char buf[10]; 23437103Sbostic register char *p; 23537103Sbostic 23637103Sbostic for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) 23737103Sbostic *p-- = n % 10 + '0'; 23837103Sbostic while (p > buf && digits-- > 0) 23937346Sbostic *p-- = pad; 24037103Sbostic return(_add(++p)); 24137103Sbostic } 24237103Sbostic 24337103Sbostic static 24437103Sbostic _add(str) 24537103Sbostic register char *str; 24637103Sbostic { 24737103Sbostic for (;; ++pt, --gsize) { 24837103Sbostic if (!gsize) 24937103Sbostic return(0); 25037103Sbostic if (!(*pt = *str++)) 25137103Sbostic return(1); 25237103Sbostic } 25337103Sbostic } 254