commit c1aa247e85a70aec8f2ec38845a666d40aa6a077 Author: heinzel Date: Tue Feb 19 14:12:59 2008 +0000 Added my implementation of unixtime. This implementation has very few reasonable code (call atol() and ctime()), but has some nice standard program stuff (parse options, print help, ...). diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..ebe4fc5 --- /dev/null +++ b/COPYING @@ -0,0 +1 @@ +This is public domain, I think. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4ec4489 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +help: + @echo "Run ./configure first!" + @echo "Or even better: take a look at the file README." +install: help +all: help diff --git a/Makefile.dist b/Makefile.dist new file mode 100644 index 0000000..4ec4489 --- /dev/null +++ b/Makefile.dist @@ -0,0 +1,5 @@ +help: + @echo "Run ./configure first!" + @echo "Or even better: take a look at the file README." +install: help +all: help diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..a4f7e0e --- /dev/null +++ b/Makefile.in @@ -0,0 +1,72 @@ +# @Makefile.in@ + +PREFIX := @PREFIX@ +BINDIR := @BINDIR@ +MAN1DIR := @MAN1DIR@ + +MAIN := unixtime +OBJS := unixtime.o +#LIBS := +MAN1 := unixtime.1 + +MANGZ := @MANGZ@ +ifeq ($(MANGZ), 1) + MAN1 := $(addsuffix .gz, $(MAN1)) +endif + +CC := @CC@ +CP := @CP@ +GZIP := @GZIP@ +INSTALL := @INSTALL@ +RM := @RM@ +STRIP := @STRIP@ +TAR := @TAR@ + +.PHONY: help strip install install-bin install-man install-man1 uninstall \ + clean distclean mrproper dist +.DEFAULT: $(MAIN) + +$(MAIN): $(OBJS) +ifeq (@STATIC@, 1) + $(CC) --static -g -o $(MAIN) $(LIBS) $(OBJS) +else + $(CC) -g -o $(MAIN) $(LIBS) $(OBJS) +endif + +%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +help: + @echo "There is no help." + +strip: $(MAIN) + $(STRIP) $(MAIN) + +install: install-bin install-man + +install-bin: strip + $(INSTALL) $(MAIN) $(BINDIR) + +install-man: install-man1 + +install-man1: $(MAN1) + $(INSTALL) $^ $(MAN1DIR) + +%.gz : % + $(GZIP) -c $< > $@ + +uninstall: + -$(RM) $(BINDIR)/$(MAIN) + cd $(MAN1DIR) ; -$(RM) $(MAN1) + +clean: + $(RM) -f *.o $(MAIN) + +distclean: clean + $(CP) Makefile.dist Makefile +mrproper: distclean + +dist: distclean + cd .. ; $(TAR) -czf $(notdir $(PWD)).tar.gz $(notdir $(PWD)) + +#end diff --git a/README b/README new file mode 100644 index 0000000..b9959d0 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +unixtime(1) converts a unix timestamp (number of seconds since epoch) +into a human readable date. + +INSTALL +======= +./configure +make +make install + diff --git a/configure b/configure new file mode 100755 index 0000000..0f72572 --- /dev/null +++ b/configure @@ -0,0 +1,291 @@ +#!/bin/sh +# +# configure +# +# A simple script to configure Makefiles +# (i.e. read Makefile.in, replace strings and write Makefile). +# +# heinzel +# +# $Id: configure,v 1.1 2008/02/19 14:12:59 heinzel Exp $ +# +VERSION='configure Version 0.1 $Revision: 1.1 $ ($Date: 2008/02/19 14:12:59 $ $Author: heinzel $)' + +### config ### +FILES="" +FILES_DEF="configure.files" + +TEMPLATE_SUFFIX=".in" +MACROS_DEF="configure.macros" + +MACROS="CTEMPLATE" +MACRO_CTEMPLATE="@CFILE@ (created by configure script)" + +### functions ### +function print_help() { + cat </dev/null ; then + MACROS="$MACROS ${name}" + fi +} + +function eval_macro() { + local name="$1" + local text="" + local return="" + + eval text="\$MACRO_${name}" + while : ; do + # Test if text contains more macros. + echo "$text" | grep -E "@[A-Z][A-Z0-9]*@" >/dev/null + r=$? + if test "1${r}" != "10" ; then + # Text is macro free. + return="$text" + break + else + # Get the last macro name from text... + sm_name="`echo $text | sed -e 's=^.*@\([A-Z][A-Z0-9]*\)@.*$=\1='`" + # Resolve it... + sm_text="`eval_macro $sm_name`" + # Substitute macro... + text="`echo $text | sed -e 's=@'${sm_name}'@='${sm_text}'=g'`" + fi + done + + echo "$return" +} + +function load_defaults() { + local inc="${MACROS_DEF:-configure.macros}" + local i=0 + local line="" + + if test "X${inc}" = "X" ; then + return 1 + fi + if test ! -r "$inc" -o -d "$inc" ; then + echo "${inc}: not a readable file." >&2 + return 1 + fi + + while read line ; do + i="`expr $i + 1`" + case "$line" in + \#*|\ *|'') + continue + ;; + *=*) + set_macro "$line" + ;; + *) + echo "Warning: $inc: unexpected line ($i)." >&2 + ;; + esac + done < "$inc" +} + +function configure() { + local file="$1" + local ext="${TEMPLATE_SUFFIX:-.in}" + local template="" + + local static_file="" + + local expr="" + local name="" + local text="" + + if test "X${file}" = "X" ; then + echo "No filename given." >&2 + return 1 + fi + template="${file}${ext}" + if test ! -r "$template" -o -d "$template" ; then + echo "$file: cannot read template ($template)." + return 1 + fi + + set_macro CFILE="$file" + ctext="`eval_macro CTEMPLATE`" + cexpr="s=@${template}@=${ctext}=g" + + if test "X${CONFIGURE_STATIC_FILE}" != "X" ; then + static_file="$CONFIGURE_STATIC_FILE" + read expr < "$static_file" + else + static_file="`mktemp configure.tmp.XXXXXX`" + if test "1$?" -ne "10" -o "X${static_file}" = "X" \ + -o ! -w "$static_file" ; then + echo "Cannot create temp file." >&2 + return 1 + fi + CONFIGURE_STATIC_FILE="$static_file" + + expr="" + for name in $MACROS ; do + case "$name" in + CFILE|CTEMPLATE) + continue + ;; + esac + text="`eval_macro $name`" + expr="s=@$name@=$text=g +$expr" + done + + echo "$expr" > "$static_file" + fi + + sed -e "$cexpr" -e "$expr" "$template" > "$file" +} + +function clean_up() { + if test "X${CONFIGURE_STATIC_FILE}" != "X" -a -f "$CONFIGURE_STATIC_FILE" ; then + rm "$CONFIGURE_STATIC_FILE" + fi +} + +### set options ### +load_defaults + +while test "1$#" -gt "10" ; do +case "$1" in +-h|--help) + print_help + exit 0 + ;; +-V|--version) + print_version + exit 0 + ;; +--with-*|--without-*) + set_macro "$1" + shift + ;; +--enable-*|--disable-*) + set_macro "$1" + shift + ;; +--*=*) + set_macro "$1" + shift + ;; +--*) + case "$2" in + ''|-*) + set_macro "${1}=1" + shift + ;; + *) + set_macro "$1" "$2" + shift + shift + ;; + esac + ;; +esac +done + +### action ### + +files="$FILES" +if test "X${FILES_DEF}" != "X" -a -f "$FILES_DEF" ; then + read buf < "$FILES_DEF" + files="$files $buf" +fi + + +if test "X${files}" = "X" ; then + echo "No files to configure." >&2 + echo " Make sure '$FILES_DEF' is there and readable." >&2 + exit 1 +fi + +for f in $files ; do + echo "Creating file $f..." + configure $f +done + +clean_up +### end ### diff --git a/configure.files b/configure.files new file mode 100644 index 0000000..f3c7a7c --- /dev/null +++ b/configure.files @@ -0,0 +1 @@ +Makefile diff --git a/configure.macros b/configure.macros new file mode 100644 index 0000000..80912f3 --- /dev/null +++ b/configure.macros @@ -0,0 +1,35 @@ +# configure.macros + +# Directories +PREFIX="/usr/local" +BINDIR="@PREFIX@/bin" +SBINDIR="@PREFIX@/sbin" +MANDIR="@PREFIX@/share/man" +MAN1DIR="@MANDIR@/man1" +MAN2DIR="@MANDIR@/man2" +MAN3DIR="@MANDIR@/man3" +MAN4DIR="@MANDIR@/man4" +MAN5DIR="@MANDIR@/man5" +MAN6DIR="@MANDIR@/man6" +MAN7DIR="@MANDIR@/man7" +MAN8DIR="@MANDIR@/man8" +MAN9DIR="@MANDIR@/man9" + +# Programms +CAT="cat" +CC="cc" +CP="cp" +GZIP="gzip" +INSTALL="install" +RM="rm" +SHELL="/bin/sh" +STRIP="strip" +TAR="tar" +ZCAT="zcat" + +# Magic macros +# @CFILE@ will be expanded to the name of the file, that will be created. +# Also the current template name (e.g. @Makefile.in@) can be used as a macro +# that will be expanded to another macro named CTEMPLATE (which can be +# defined here or will default to a buildin text). +#end diff --git a/unixtime.1 b/unixtime.1 new file mode 100644 index 0000000..8e7f06d --- /dev/null +++ b/unixtime.1 @@ -0,0 +1,25 @@ +.\" unixtime.1 +.TH UNIXTIME 1 "Feb. 2008" "heinzel" + +.SH NAME +unixtime \- converts a unix timestamp into a human readable date + +.SH SYNOPSIS +.B unixtime [-h, --help] [-V, --version] + +.SH DESCRIPTION +\fBunixtime\fP is similar to the standard c library function \fBctime()\fP + +.SH OPTIONS +An integer , which is a number of seconds since the Epoch. + +.SH "BUGS" +Since I have no real understanding of C, I am sure, there are. + +.SH "AUTHOR" +heinzel + +.SH "SEE ALSO" +.BR time (2), +.BR ctime (3) + diff --git a/unixtime.c b/unixtime.c new file mode 100644 index 0000000..80337be --- /dev/null +++ b/unixtime.c @@ -0,0 +1,138 @@ +/* + * unixtime.c + */ + +#include +#include +#include +#include +#include +#include + +/* symbols */ +#define TRUE 1 +#define FALSE 0 +#define VERSION "0.1" + +/* prototypes */ +int print_version(void); +int print_help(void); + +/* definition of extern objects */ +char *progname; +const char *version = VERSION; + +/* + * main + */ +int main(int argc, char** argv) { + int i; + int j; + char c; + char *p; + size_t l; + time_t t = 0; + struct tm *tm; + + /* Store program name without path + * (will be used in e.g. error messages) */ + if( (progname = strdup(basename(argv[0]))) == NULL ) { + fprintf(stderr, "%s: ", basename(argv[0])); + perror(NULL); + exit(EX_OSERR); + } + + /* Parse command line options */ + for( i = 1 ; i < argc ; i++ ) { + if(!strncmp("--", argv[i], 2)) { + /* Current argument is a GNU long option */ + if(!strcmp( "--help", argv[i])) { + print_help(); + exit(EX_OK); + } else if(!strcmp("--version", argv[i])) { + print_version(); + exit(EX_OK); + } else { + fprintf(stderr, "%s: invalid option: %s\n", progname, argv[i]); + fprintf(stderr, "Try '%s -h' for help.\n", progname); + exit(EX_USAGE); + } + } else if(!strncmp("-", argv[i], 1)) { + /* Current argument is one or more short options */ + p = argv[i]; + for( j = 1 ; (c = p[j]) != '\0' ; j++) { + switch(c) { + case 'h': + print_help(); + exit(EX_OK); + break; + case 'V': + print_version(); + exit(EX_OK); + break; + default: + fprintf(stderr, "%s: invalid option: %c\n", progname, c); + fprintf(stderr, "Try '%s -h' for help.\n", progname); + exit(EX_USAGE); + } + } + } else { + /* This is the first argument, that is not an option. + * It will be taken as timestamp. */ + t = atol(argv[i]); + l = strlen(argv[i]); + if((p = malloc(l + 1)) != NULL) { + snprintf(p, l + 1, "%d", t); + if(strcmp(argv[i], p)) { + fprintf(stderr, "%s: not numeric: %s\n", progname, + argv[i]); + exit(EX_DATAERR); + } + free(p); + } else { + fprintf(stderr, "%s: Warning: cannot allocate memory" + " to do numeric test on input.\n", progname); + } + break; + } + } + + p = ctime((& t)); + if(p == NULL) { + fprintf(stderr, "%s: unrecognized date '%d'.\n", progname, time); + exit(EX_DATAERR); + } + fputs(p, stdout); + exit(EX_OK); +} + +int print_version( void ) { + printf("%s Version %s\n",progname, version); + return TRUE; +} + +int print_help( void ) { + time_t t = 0; + char *p; + char *p2; + + printf("\n"); + printf("%s converts a unix timestamp into a human readable date.\n", + progname); + printf("\n"); + printf("Usage: unixtime [-h, --help] [-V, --version] \n"); + printf("\n"); + printf("Where is the number of seconds since the Epoch\n"); + if((p = strdup(ctime(& t))) != NULL) { + /* ctime() return the date as string with an appended new line. + * Since we do not want the new line to be printed, we terminate + * the string at the position of the new line. */ + if((p2 = strstr(p, "\n")) != NULL) + strcpy(p2, "\0"); + printf("(i.e. %s).\n", p); + free(p); + } + printf("\n"); + + return TRUE; +}