pkgsrc-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: How to change mail/thunderbird date format?
Rhialto wrote:
> On Fri 22 Aug 2008 at 03:02:44 +0200, Rhialto wrote:
> > Clever! I'll try that since it seems to work
> Thunderbird only seems to use the formats "%x %H:%M" and "%H:%M" so this
> is easy enough to cheat and just do 2 strcmp()s. Works fine! Thanks!
> Maybe I'll use this trick more often...
I've attached a more complete implementation of the hack which can
handle arbitrary formats. Just for the heck of it.
--
Christian
/**
* Wrap strftime() to use ISO 8601 as the locale's time and date
* representation.
*
* Compile as shared object (very platform/compile dependend):
* cc -W -Wall -Wformat -Wshadow -shared strftime_8601.c -o strftime_8601.so
*
* Add -DDEBUG to print the format string passed to strftime() to /dev/tty.
*
* Use and test:
* LD_PRELOAD=./strftime_override.so date +'[%x] [%X] [%c]'
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <dlfcn.h>
#include <errno.h>
#ifdef DEBUG
#include <unistd.h>
#include <fcntl.h>
#endif /* DEBUG */
typedef void (*func_ptr)(void);
typedef size_t (*strftime_func_ptr)(char *, size_t, const char *, const struct
tm *);
size_t strftime(char *, size_t, const char *, const struct tm *)
__attribute__((alias ("strftime_8601")));
static func_ptr
get_libc_symbol(const char *symbol)
{
static void *handle;
static const func_ptr zero_func;
func_ptr func = zero_func;
#ifdef RTLD_NEXT
handle = RTLD_NEXT;
#else /* !RTLD_NEXT */
if (!handle) {
handle = dlopen("libc.so", RTLD_NOW);
}
#endif /* RTLD_NEXT */
if (handle) {
func = dlsym(handle, symbol);
if (!func) {
errno = ENOSYS;
}
} else {
errno = ENOENT;
}
return func;
}
static inline void
trace(const char *format)
{
(void) format;
#ifdef DEBUG
{
int fd = open("/dev/tty", O_WRONLY, 0);
if (fd >= 0) {
write(fd, format, strlen(format));
write(fd, "\n", 1);
close(fd);
}
}
#endif /* DEBUG */
}
size_t
strftime_real(char *buf, size_t maxsize,
const char *format, const struct tm *timeptr)
{
static strftime_func_ptr func;
if (!func) {
func = (strftime_func_ptr) get_libc_symbol("strftime");
}
return (*func)(buf, maxsize, format, timeptr);
}
static inline size_t
size_incr(size_t a, size_t b)
{
size_t ret = a + b;
return ret < a ? (size_t)-1 : ret;
}
/**
* Modify format string to use ISO 8601 format as locale's format
* and calculate required buffer size.
*
* @param dst buffer to hold modified format. May be NULL.
* @param size size of dst buffer.
* @return buffer size required to hold modified format string.
*/
static size_t
replace(char *dst, size_t size, const char *format)
{
char buf[] = "%%";
size_t ret;
int c;
ret = 1; /* terminating NUL is mandatory */
if (dst && size > 0) {
size--; /* reserve 1 byte for terminating NUL */
} else {
dst = NULL;
}
do {
const char *s;
size_t slen;
c = *format++;
if ('%' == c) {
c = *format++;
switch (c) {
case 'X': s = "%H:%M:%S"; break;
case 'x': s = "%Y-%m-%d"; break;
case 'c': s = "%Y-%m-%d %H:%M:%S"; break;
default: buf[1] = c;
s = &buf[0];
}
} else {
buf[1] = c;
s = &buf[1];
}
slen = strlen(s);
if (dst && size > 0) {
size_t n = slen < size ? slen : size;
memcpy(dst, s, n);
dst += n;
size -= n;
}
ret = size_incr(ret, slen);
} while ('\0' != c);
if (dst) {
*dst = '\0';
}
return ret;
}
size_t
strftime_8601(char *buf, size_t maxsize,
const char *format, const struct tm *timeptr)
{
char *allocated = NULL;
size_t ret;
if (format && buf && maxsize > 0 && timeptr) {
size_t size;
trace(format);
size = replace(NULL, 0, format);
if (NULL == (allocated = malloc(size)))
return 0;
replace(allocated, size, format);
format = allocated;
}
ret = strftime_real(buf, maxsize, format, timeptr);
free(allocated);
return ret;
}
Home |
Main Index |
Thread Index |
Old Index