From c1aa247e85a70aec8f2ec38845a666d40aa6a077 Mon Sep 17 00:00:00 2001 From: heinzel Date: Tue, 19 Feb 2008 14:12:59 +0000 Subject: [PATCH] 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, ...). --- COPYING | 1 + Makefile | 5 + Makefile.dist | 5 + Makefile.in | 72 ++++++++++++ README | 9 ++ configure | 291 +++++++++++++++++++++++++++++++++++++++++++++++ configure.files | 1 + configure.macros | 35 ++++++ unixtime.1 | 25 ++++ unixtime.c | 138 ++++++++++++++++++++++ 10 files changed, 582 insertions(+) create mode 100644 COPYING create mode 100644 Makefile create mode 100644 Makefile.dist create mode 100644 Makefile.in create mode 100644 README create mode 100755 configure create mode 100644 configure.files create mode 100644 configure.macros create mode 100644 unixtime.1 create mode 100644 unixtime.c 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; +}