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