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, ...).
This commit is contained in:
heinzel
2008-02-19 14:12:59 +00:00
commit c1aa247e85
10 changed files with 582 additions and 0 deletions

1
COPYING Normal file
View File

@@ -0,0 +1 @@
This is public domain, I think.

5
Makefile Normal file
View File

@@ -0,0 +1,5 @@
help:
@echo "Run ./configure first!"
@echo "Or even better: take a look at the file README."
install: help
all: help

5
Makefile.dist Normal file
View File

@@ -0,0 +1,5 @@
help:
@echo "Run ./configure first!"
@echo "Or even better: take a look at the file README."
install: help
all: help

72
Makefile.in Normal file
View File

@@ -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

9
README Normal file
View File

@@ -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

291
configure vendored Executable file
View File

@@ -0,0 +1,291 @@
#!/bin/sh
#
# configure
#
# A simple script to configure Makefiles
# (i.e. read Makefile.in, replace strings and write Makefile).
#
# heinzel <heinzel@heinzelwelt.de>
#
# $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 <<EOH
configure create files by processing templates and replace macros.
For now macros are simple name-value pairs. Use strings like @NAME@ within
the template files and configure will replace those strings by the named
value while creating the resulting files.
Usage: ./configure [OPTIONS]
Options:
-h, --help
-V, --version
Generic Options (and default values):
EOH
for m in $MACROS ; do
case "$m" in
CFILE|CTEMPLATE)
continue
;;
esac
name="`echo $m | tr [[:upper:]] [[:lower:]]`"
text="`eval_macro $m`"
case "$text" in
0)
output=" --without-${name}"
;;
1)
output=" --with-${name}"
;;
*)
output=" --${name} $text"
;;
esac
echo "$output"
done
echo ""
cat <<EOH
Files:
This script will create following files: $FILES
or read file names to create from '$FILES_DEF'
The templates have to end with '$TEMPLATE_SUFFIX'
The macros can be defined in '$MACROS_DEF'
EOH
}
function print_version() {
echo "$VERSION"
}
function set_macro() {
case "$1" in
'')
return 1
;;
--with-*|--enable-*)
name="`echo $1 | cut -f1 -d= | cut -f4- -d- | tr [[:lower:]] [[:upper:]]`"
text="1"
;;
--without-*|--disable-*)
name="`echo $1 | cut -f1 -d= | cut -f4- -d- | tr [[:lower:]] [[:upper:]]`"
text="0"
;;
--*=*)
name="`echo $1 | cut -f1 -d= | cut -c3- | tr [[:lower:]] [[:upper:]]`"
text="`echo $1 | cut -f2- -d=`"
;;
--*)
name="`echo $1 | cut -c3- | tr [[:lower:]] [[:upper:]]`"
text="$2"
;;
*=*)
name="`echo $1 | cut -f1 -d= | tr [[:lower:]] [[:upper:]]`"
text="`echo $1 | cut -f2- -d=`"
;;
*)
name="`echo $1 | tr [[:lower:]] [[:upper:]]`"
text=""
;;
esac
eval MACRO_${name}=${text}
if ! expr " $MACROS " : ".* $name .*" >/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 ###

1
configure.files Normal file
View File

@@ -0,0 +1 @@
Makefile

35
configure.macros Normal file
View File

@@ -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

25
unixtime.1 Normal file
View File

@@ -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] <TIMESTAMP>
.SH DESCRIPTION
\fBunixtime\fP is similar to the standard c library function \fBctime()\fP
.SH OPTIONS
An integer <TIMESTAMP>, 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 <heinzel@heinzelwelt.de>
.SH "SEE ALSO"
.BR time (2),
.BR ctime (3)

138
unixtime.c Normal file
View File

@@ -0,0 +1,138 @@
/*
* unixtime.c
*/
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <time.h>
/* 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] <TIMESTAMP>\n");
printf("\n");
printf("Where <TIMESTAMP> 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;
}