
Newsgroups: alt.sources From: jef@netcom.com (Jef Poskanzer) Subject: date_parse - simple date parsing routine and programs Message-ID: <jefD3uzqC.Mos@netcom.com> Reply-To: Jef Poskanzer <jef@netcom.com> Organization: Paratheo-Anametamystikhood Of Eris Esoteric Date: Sat, 11 Feb 1995 23:25:24 GMT Lines: 2048 Sender: jef@netcom18.netcom.com date_parse - date parsing routine and programs version 1.0 of 11feb95 For a while now I've been somewhat unhappy with the various date-parsing routines available - yacc-based, lex-based, ad-hoc. Large code size and not very portable are the main complaints. So I wrote a new one that just does a bunch of sscanf's until one matches. Slow, but small and portable. To figure out what formats to support I did a survey of Date: lines in a bunch of Usenet articles. The following two formats accounted for more than 99% of all articles: N mth YYYY HH:MM:SS ampm zone wdy, N mth YYYY HH:MM:SS ampm zone I added Unix ctime() format and a few others: wdy mth N HH:MM:SS ampm zone YYYY HH:MM:SS ampm zone N mth YYYY N mth YYYY HH:MM:SS ampm No-zone, no-seconds, and no-am/pm versions of each are also supported. Note that dd/mm/yy and mm/dd/yy are NOT supported - those formats are dumb. Aside from the date-parsing routine, this package includes some programs that exercise it: o date_sort - sort a file's lines by date o date_order - order a list of files by netnews/mail-format Date: lines o deltime - subtract two times and show the difference o xmit_time - figure transmission time of netnews articles - - - - - - - - - - #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile # README # ctime.c # date_order.1 # date_order.c # date_parse.3 # date_parse.c # date_sort.1 # date_sort.c # deltime.1 # deltime.c # dptest.c # test_input # test_output # xmit_time.1 # xmit_time.c # This archive created: Sat Feb 11 15:21:30 1995 # By: Jef Poskanzer export PATH; PATH=/bin:$PATH echo shar: extracting "'Makefile'" '(1873 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# Makefile for date_parse and friends X X# CONFIGURE: the directory where you want the library installed XLIBDIR = /usr/local/lib X X# CONFIGURE: the directory where you want the executables installed XBINDIR = /usr/local/bin X X# CONFIGURE: the directory tree where you want the man pages installed XMANDIR = /usr/local/man X X# CONFIGURE: type of system - uncomment one of these XDEFINES = -DBSD X#DEFINES = -DSYSV X X# CONFIGURE: your compiler X#CC = cc XCC = gcc -ansi -pedantic X X# CONFIGURE: your compiler flags XCFLAGS = -O $(DEFINES) X#CFLAGS = -g $(DEFINES) X#CFLAGS = $(DEFINES) X X# CONFIGURE: your loader flags XLDFLAGS = -s X#LDFLAGS = X X# End of configurable definitions. X XLIB = libdate_parse.a XEXES = date_order date_sort deltime xmit_time X Xall: $(LIB) $(EXES) X Xlibdate_parse.a: date_parse.o X rm -f libdate_parse.a X ar rc libdate_parse.a date_parse.o X -ranlib libdate_parse.a X Xdate_order: date_order.c $(LIB) X $(CC) $(CFLAGS) $(LDFLAGS) date_order.c $(LIB) -o date_order X Xdate_sort: date_sort.c $(LIB) X $(CC) $(CFLAGS) $(LDFLAGS) date_sort.c $(LIB) -o date_sort X Xdeltime: deltime.c $(LIB) X $(CC) $(CFLAGS) $(LDFLAGS) deltime.c $(LIB) -o deltime X Xxmit_time: xmit_time.c $(LIB) X $(CC) $(CFLAGS) $(LDFLAGS) xmit_time.c $(LIB) -o xmit_time X Xctime: ctime.c X $(CC) $(CFLAGS) $(LDFLAGS) ctime.c -o ctime X X.c.o: X $(CC) $(CFLAGS) -c $< X Xtest: all dptest X ./dptest < test_input | diff test_output - X Xdptest: dptest.c $(LIB) X $(CC) $(CFLAGS) $(LDFLAGS) dptest.c $(LIB) -o dptest X Xinstall: all X for i in $(LIB) ; do \ X rm -f $(LIBDIR)/$$i ; \ X cp $$i $(LIBDIR) ; \ X done X for i in $(EXES) ; do \ X rm -f $(BINDIR)/$$i ; \ X cp $$i $(BINDIR) ; \ X done X rm -f $(MANDIR)/man3/date_parse.3 X cp date_parse.3 $(MANDIR)/man3 X for i in $(EXES) ; do \ X rm -f $(MANDIR)/man1/$$i.1 ; \ X cp $$i.1 $(MANDIR)/man1 ; \ X done X Xclean: X rm -f *.o *.a $(EXES) dptest ctime a.out core SHAR_EOF if test 1873 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 1873 characters)' fi fi # end of overwriting check echo shar: extracting "'README'" '(1546 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^X//' << \SHAR_EOF > 'README' X date_parse - date parsing routine and programs X version 1.0 of 11feb95 X XFor a while now I've been somewhat unhappy with the various Xdate-parsing routines available - yacc-based, lex-based, ad-hoc. Large Xcode size and not very portable are the main complaints. So I wrote a Xnew one that just does a bunch of sscanf's until one matches. Slow, Xbut small and portable. To figure out what formats to support I did a Xsurvey of Date: lines in a bunch of Usenet articles. The following two Xformats accounted for more than 99% of all articles: X X N mth YYYY HH:MM:SS ampm zone X wdy, N mth YYYY HH:MM:SS ampm zone X XI added Unix ctime() format and a few others: X X wdy mth N HH:MM:SS ampm zone YYYY X HH:MM:SS ampm zone N mth YYYY X N mth YYYY X HH:MM:SS ampm X XNo-zone, no-seconds, and no-am/pm versions of each are also supported. XNote that dd/mm/yy and mm/dd/yy are NOT supported - those formats are Xdumb. X XAside from the date-parsing routine, this package includes some programs Xthat exercise it: X o date_sort - sort a file's lines by date X o date_order - order a list of files by netnews/mail-format Date: lines X o deltime - subtract two times and show the difference X o xmit_time - figure transmission time of netnews articles X XSee the manual entries for more details. X X XTo install: X Unpack the files. X Edit the Makefile to change the configuration options if necessary. X Make test to check that it works right. X Make install. X XComments to: X Jef Poskanzer jef@netcom.com jef@well.com SHAR_EOF if test 1546 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 1546 characters)' fi fi # end of overwriting check echo shar: extracting "'ctime.c'" '(225 characters)' if test -f 'ctime.c' then echo shar: will not over-write existing file "'ctime.c'" else sed 's/^X//' << \SHAR_EOF > 'ctime.c' X/* simple debugging tool */ X X#include <stdio.h> X#include <time.h> X Xvoid Xmain( argc, argv ) X int argc; X char* argv[]; X { X time_t t; X X t = atoi( argv[1] ); X printf( "%s\n", ctime( &t ) ); X exit( 0 ); X } SHAR_EOF if test 225 -ne "`wc -c < 'ctime.c'`" then echo shar: error transmitting "'ctime.c'" '(should have been 225 characters)' fi fi # end of overwriting check echo shar: extracting "'date_order.1'" '(1535 characters)' if test -f 'date_order.1' then echo shar: will not over-write existing file "'date_order.1'" else sed 's/^X//' << \SHAR_EOF > 'date_order.1' X.TH date_order 1 "11 February 1995" X.SH NAME Xdate_order - order filenames by date X.SH SYNOPSIS X.B date_order X.RI [ file X.IR ... ] X.SH DESCRIPTION X.PP XGiven a set of filenames as arguments, looks in each file for Xan email/netnews-format Date: line and writes the filenames out again Xsorted by the dates. X.PP XThis does not change or rearrange the actual files in any way. XAll it does it produce a new list of the fileNAMEs, sorted by the dates Xin the files. X.PP XThe intended use is with a shell's backquote construct. XFor instance, if you have a version of uudecode that automatically Xskips headers and trailers and handles multiple input and output files X(such as my version), Xthen you can decode the entire current contents of a picture-newsgroup spool Xdirectory with one command: X.nf X uudecode `date_order *` X.fi XThe reason you want to use date_order instead of just doing "uudecode *" Xis that netnews articles often arrive out of order. XUsing date_order hands them to uudecode in the order they were posted. X.SH "SEE ALSO" Xdate_sort(1), deltime(1), xmit_time(1), date_parse(3), uudecode(1) X.SH AUTHOR XCopyright (C) 1995 by Jef Poskanzer. X.\" Permission to use, copy, modify, and distribute this software and its X.\" documentation for any purpose and without fee is hereby granted, provided X.\" that the above copyright notice appear in all copies and that both that X.\" copyright notice and this permission notice appear in supporting X.\" documentation. This software is provided "as is" without express or X.\" implied warranty. SHAR_EOF if test 1535 -ne "`wc -c < 'date_order.1'`" then echo shar: error transmitting "'date_order.1'" '(should have been 1535 characters)' fi fi # end of overwriting check echo shar: extracting "'date_order.c'" '(3040 characters)' if test -f 'date_order.c' then echo shar: will not over-write existing file "'date_order.c'" else sed 's/^X//' << \SHAR_EOF > 'date_order.c' X/* date_order - order filenames by date X** X** Copyright (C) 1995 by Jef Poskanzer <jef@netcom.com>. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <string.h> X#include <malloc.h> X#include <time.h> X Xextern time_t date_parse(); X Xstatic void usage(); Xstatic time_t date_file(); Xstatic int file_compare(); Xstatic char* my_malloc(); Xstatic char* my_realloc(); Xstatic void out_of_mem(); X Xstatic char* argv0; X Xstruct file X { X char* name; X time_t date; X }; X Xstatic int maxfiles, nfiles; Xstatic struct file* files; X Xvoid Xmain( argc, argv ) X int argc; X char* argv[]; X { X int argn; X int i; X X argv0 = argv[0]; X argn = 1; X if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) X usage(); X X maxfiles = argc - argn; X files = (struct file*) my_malloc( maxfiles * sizeof(struct file) ); X nfiles = 0; X X while ( argn < argc ) X { X files[nfiles].name = (char*) my_malloc( strlen( argv[argn] ) + 1 ); X (void) strcpy( files[nfiles].name, argv[argn] ); X files[nfiles].date = date_file( argv[argn] ); X ++nfiles; X ++argn; X } X X qsort( files, nfiles, sizeof(struct file), file_compare ); X X for ( i = 0; i < nfiles; ++i ) X { X if ( i != 0 ) X putchar( ' ' ); X fputs( files[i].name, stdout ); X } X putchar( '\n' ); X X exit( 0 ); X } X Xstatic void Xusage() X { X (void) fprintf( stderr, "usage: %s [file ...]\n", argv0 ); X exit( 1 ); X } X Xstatic time_t Xdate_file( name ) X char* name; X { X FILE* f; X char line[30000]; X time_t t; X X f = fopen( name, "r" ); X if ( f == (FILE*) 0 ) X { X perror( name ); X return (time_t) -1; X } X X for (;;) X { X if ( fgets( line, sizeof(line), f ) == (char*) 0 ) X break; X if ( line[0] == '\n' ) X break; X if ( strncmp( line, "Date:", 5 ) == 0 ) X { X (void) fclose( f ); X t = date_parse( &line[5] ); X if ( t == (time_t) -1 ) X (void) fprintf( X stderr, "%s: unparsable date in %s - %s", X argv0, name, &line[5] ); X return t; X } X } X X (void) fprintf( stderr, "%s: no Date: line found in %s\n", argv0, name ); X (void) fclose( f ); X return (time_t) -1; X } X Xstatic int Xfile_compare( f1, f2 ) X struct file* f1; X struct file* f2; X { X return f1->date - f2->date; X } X Xstatic char* Xmy_malloc( size ) X unsigned size; X { X char* r; X X r = malloc( size ); X if ( r == (char*) 0 ) X out_of_mem(); X return r; X } X Xstatic char* Xmy_realloc( p, size ) X char* p; X unsigned size; X { X char* r; X X r = realloc( p, size ); X if ( r == (char*) 0 ) X out_of_mem(); X return r; X } X Xstatic void Xout_of_mem() X { X (void) fprintf( stderr, "%s: out of memory\n", argv0 ); X exit( 1 ); X } SHAR_EOF if test 3040 -ne "`wc -c < 'date_order.c'`" then echo shar: error transmitting "'date_order.c'" '(should have been 3040 characters)' fi fi # end of overwriting check echo shar: extracting "'date_parse.3'" '(1789 characters)' if test -f 'date_parse.3' then echo shar: will not over-write existing file "'date_parse.3'" else sed 's/^X//' << \SHAR_EOF > 'date_parse.3' X.TH date_parse 3 "11 February 1995" X.SH NAME Xdate_parse - parse string dates into internal form X.SH SYNOPSIS Xtime_t date_parse( char* str ) X.SH DESCRIPTION X.PP XParses a date string into standard Unix internal time form (seconds Xsince epoch). XThe date should be in one of the following formats: X.nf X N mth YYYY HH:MM:SS ampm zone X HH:MM:SS ampm zone N mth YYYY X wdy, N mth YYYY HH:MM:SS ampm zone X wdy mth N HH:MM:SS ampm zone YYYY X N mth YYYY X HH:MM:SS ampm X.fi XNo-zone, no-seconds, and no-am/pm versions of each are also allowed. XAny missing parts default to the current date/time. XNote that dd/mm/yy and mm/dd/yy are not supported - those formats are dumb. X.SH SPEED X.PP XThe implementation is just a bunch of sscanf's - small and portable, but slow. XStill, it's not that bad. XOn a SPARCstation 2 parsing ~70000 random dates, the average time Xwas 0.94 msec/date. XThis compares surprising well with the lex-based date parser from Xthe MH package, which took 0.34 msec/date in the same test. XThe yacc-based parser used in many netnews packages is about halfway Xbetween the two. X.PP XIn any application which has to open a file for each date - and both XMH and netnews are such applications - the difference in date parsing Xspeed will not be perceptible to the user. X.SH "SEE ALSO" Xdate_sort(1), date_order(1), deltime(1), xmit_time(1) X.SH AUTHOR XCopyright (C) 1995 by Jef Poskanzer. X.\" Permission to use, copy, modify, and distribute this software and its X.\" documentation for any purpose and without fee is hereby granted, provided X.\" that the above copyright notice appear in all copies and that both that X.\" copyright notice and this permission notice appear in supporting X.\" documentation. This software is provided "as is" without express or X.\" implied warranty. SHAR_EOF if test 1789 -ne "`wc -c < 'date_parse.3'`" then echo shar: error transmitting "'date_parse.3'" '(should have been 1789 characters)' fi fi # end of overwriting check echo shar: extracting "'date_parse.c'" '(19522 characters)' if test -f 'date_parse.c' then echo shar: will not over-write existing file "'date_parse.c'" else sed 's/^X//' << \SHAR_EOF > 'date_parse.c' X/* date_parse - parse string dates into internal form X** X** Copyright (C) 1995 by Jef Poskanzer <jef@netcom.com>. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X/* For a while now I've been somewhat unhappy with the various X** date-parsing routines available - yacc-based, lex-based, ad-hoc. Large X** code size and not very portable are the main complaints. So I wrote a X** new one that just does a bunch of sscanf's until one matches. Slow, X** but small and portable. To figure out what formats to support I did a X** survey of Date: lines in a bunch of Usenet articles. The following X** two formats accounted for more than 99% of all articles: X** N mth YYYY HH:MM:SS ampm zone X** wdy, N mth YYYY HH:MM:SS ampm zone X** I added Unix ctime() format and a few others: X** wdy mth N HH:MM:SS ampm zone YYYY X** HH:MM:SS ampm zone N mth YYYY X** N mth YYYY X** HH:MM:SS ampm X** No-zone, no-seconds, and no-am/pm versions of each are also supported. X** Note that dd/mm/yy and mm/dd/yy are NOT supported - those formats are X** dumb. X*/ X X#include <sys/types.h> X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include <time.h> X X#ifdef SYSV Xextern long timezone; X#define bzero(p, n) memset(p, 0, n) X#endif /* SYSV */ X X#undef DEBUG X X#ifdef DEBUG X#define DP(str) (void) fprintf( stderr, "%s\n", str ) X#else X#define DP(str) (0) X#endif X Xstruct strint { X char* s; X int i; X }; X Xstatic void Xpound_case( str ) X char* str; X { X for ( ; *str != '\0'; ++str ) X { X if ( isupper( *str ) ) X *str = tolower( *str ); X } X } X Xstatic int Xstrint_compare( v1, v2 ) X char* v1; X char* v2; X { X return strcmp( ((struct strint*) v1)->s, ((struct strint*) v2)->s ); X } X Xstatic int Xstrint_search( str, tab, n, iP ) X char* str; X struct strint* tab; X int n; X int* iP; X { X int i, h, l, r; X X l = 0; X h = n - 1; X for (;;) X { X i = ( h + l ) / 2; X r = strcmp( str, tab[i].s ); X if ( r < 0 ) X h = i - 1; X else if ( r > 0 ) X l = i + 1; X else X { X *iP = tab[i].i; X return 1; X } X if ( h < l ) X return 0; X } X } X X#define AMPM_NONE 0 X#define AMPM_AM 1 X#define AMPM_PM 2 Xstatic int Xampm_fix( hour, ampm ) X int hour, ampm; X { X switch ( ampm ) X { X case AMPM_NONE: X break; X case AMPM_AM: X if ( hour == 12 ) X hour = 0; X break; X case AMPM_PM: X if ( hour != 12 ) X hour += 12; X break; X } X return hour; X } X Xstatic int Xscan_ampm( str_ampm, ampmP ) X char* str_ampm; X int* ampmP; X { X static struct strint ampm_tab[] = { X { "am", AMPM_AM }, { "pm", AMPM_PM }, X }; X static int sorted = 0; X X if ( ! sorted ) X { X (void) qsort( X ampm_tab, sizeof(ampm_tab)/sizeof(struct strint), X sizeof(struct strint), strint_compare ); X sorted = 1; X } X pound_case( str_ampm ); X return strint_search( X str_ampm, ampm_tab, sizeof(ampm_tab)/sizeof(struct strint), ampmP ); X } X Xstatic int Xscan_wday( str_wday, tm_wdayP ) X char* str_wday; X int* tm_wdayP; X { X static struct strint wday_tab[] = { X { "sun", 0 }, { "sunday", 0 }, X { "mon", 1 }, { "monday", 1 }, X { "tue", 2 }, { "tuesday", 2 }, X { "wed", 3 }, { "wednesday", 3 }, X { "thu", 4 }, { "thursday", 4 }, X { "fri", 5 }, { "friday", 5 }, X { "sat", 6 }, { "saturday", 6 }, X }; X static int sorted = 0; X X if ( ! sorted ) X { X (void) qsort( X wday_tab, sizeof(wday_tab)/sizeof(struct strint), X sizeof(struct strint), strint_compare ); X sorted = 1; X } X pound_case( str_wday ); X return strint_search( X str_wday, wday_tab, sizeof(wday_tab)/sizeof(struct strint), tm_wdayP ); X } X Xstatic int Xscan_mon( str_mon, tm_monP ) X char* str_mon; X int* tm_monP; X { X static struct strint mon_tab[] = { X { "jan", 0 }, { "january", 0 }, X { "feb", 1 }, { "february", 1 }, X { "mar", 2 }, { "march", 2 }, X { "apr", 3 }, { "april", 3 }, X { "may", 4 }, X { "jun", 5 }, { "june", 5 }, X { "jul", 6 }, { "july", 6 }, X { "aug", 7 }, { "august", 7 }, X { "sep", 8 }, { "september", 8 }, X { "oct", 9 }, { "october", 9 }, X { "nov", 10 }, { "november", 10 }, X { "dec", 11 }, { "december", 11 }, X }; X static int sorted = 0; X X if ( ! sorted ) X { X (void) qsort( X mon_tab, sizeof(mon_tab)/sizeof(struct strint), X sizeof(struct strint), strint_compare ); X sorted = 1; X } X pound_case( str_mon ); X return strint_search( X str_mon, mon_tab, sizeof(mon_tab)/sizeof(struct strint), tm_monP ); X } X Xstatic int Xscan_gmtoff( str_gmtoff, gmtoffP ) X char* str_gmtoff; X int* gmtoffP; X { X static struct strint gmtoff_tab[] = { X { "gmt", 0 }, { "utc", 0 }, { "ut", 0 }, X { "0000", 0 }, { "+0000", 0 }, { "-0000", 0 }, X { "0100", 3600 }, { "+0100", 3600 }, { "-0100", -3600 }, X { "0200", 7200 }, { "+0200", 7200 }, { "-0200", -7200 }, X { "0300", 10800 }, { "+0300", 10800 }, { "-0300", -10800 }, X { "0400", 14400 }, { "+0400", 14400 }, { "-0400", -14400 }, X { "0500", 18000 }, { "+0500", 18000 }, { "-0500", -18000 }, X { "0600", 21600 }, { "+0600", 21600 }, { "-0600", -21600 }, X { "0700", 25200 }, { "+0700", 25200 }, { "-0700", -25200 }, X { "0800", 28800 }, { "+0800", 28800 }, { "-0800", -28800 }, X { "0900", 32400 }, { "+0900", 32400 }, { "-0900", -32400 }, X { "1000", 36000 }, { "+1000", 36000 }, { "-1000", -36000 }, X { "1100", 39600 }, { "+1100", 39600 }, { "-1100", -39600 }, X { "1200", 43200 }, { "+1200", 43200 }, { "-1200", -43200 }, X { "jst", 7200 }, { "jdt", 10800 }, X { "bst", -3600 }, X { "nst", -12600 }, X { "ast", -14400 }, { "edt", -10800 }, X { "est", -18000 }, { "edt", -14400 }, X { "cst", -21600 }, { "cdt", -18000 }, X { "mst", -25200 }, { "mdt", -21600 }, X { "pst", -28800 }, { "pdt", -25200 }, X { "yst", -32400 }, { "ydt", -28800 }, X { "hst", -36000 }, { "hdt", -32400 }, X { "a", -3600 }, { "b", -7200 }, { "c", -10800 }, { "d", -14400 }, X { "e", -18000 }, { "f", -21600 }, { "g", -25200 }, { "h", -28800 }, X { "i", -32400 }, { "k", -36000 }, { "l", -39600 }, { "m", -43200 }, X { "n", -3600 }, { "o", -7200 }, { "p", -10800 }, { "q", -14400 }, X { "r", -18000 }, { "s", -21600 }, { "t", -25200 }, { "u", -28800 }, X { "v", -32400 }, { "w", -36000 }, { "x", -39600 }, { "y", -43200 }, X }; X static int sorted = 0; X X if ( ! sorted ) X { X (void) qsort( X gmtoff_tab, sizeof(gmtoff_tab)/sizeof(struct strint), X sizeof(struct strint), strint_compare ); X sorted = 1; X } X pound_case( str_gmtoff ); X return strint_search( X str_gmtoff, gmtoff_tab, sizeof(gmtoff_tab)/sizeof(struct strint), X gmtoffP ); X } X Xstatic int Xis_leap( year ) X int year; X { X return year % 400? ( year % 100 ? ( year % 4 ? 0 : 1 ) : 0 ) : 1; X } X X/* Basically the same as mktime(). */ Xstatic time_t Xtm_to_time( tmP ) X struct tm* tmP; X { X time_t t; X static int monthtab[12] = { X 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; X X /* Years since epoch, converted to days. */ X t = ( tmP->tm_year - 70 ) * 365; X /* Leap days for previous years. */ X t += ( tmP->tm_year - 68 ) / 4; X /* Days for the beginning of this month. */ X t += monthtab[tmP->tm_mon]; X /* Leap day for this year. */ X if ( tmP->tm_mon >= 2 && is_leap( tmP->tm_year ) ) X ++t; X /* Days since the beginning of this month. */ X t += tmP->tm_mday - 1; /* 1-based field */ X /* Hours, minutes, and seconds. */ X t = t * 24 + tmP->tm_hour; X t = t * 60 + tmP->tm_min; X t = t * 60 + tmP->tm_sec; X X return t; X } X Xtime_t Xdate_parse( str ) X char* str; X { X time_t now; X struct tm* now_tmP; X struct tm tm; X char* cp; X char str_mon[500], str_wday[500], str_gmtoff[500], str_ampm[500]; X int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, gmtoff; X int ampm, got_zone; X time_t t; X X /* Initialize tm with relevant parts of current local time. */ X now = time( (time_t*) 0 ); X now_tmP = localtime( &now ); X X bzero( (char*) &tm, sizeof(struct tm) ); X tm.tm_sec = now_tmP->tm_sec; X tm.tm_min = now_tmP->tm_min; X tm.tm_hour = now_tmP->tm_hour; X tm.tm_mday = now_tmP->tm_mday; X tm.tm_mon = now_tmP->tm_mon; X tm.tm_year = now_tmP->tm_year; X ampm = AMPM_NONE; X got_zone = 0; X X /* Find local zone offset. This is the only real area of X ** non-portability, and it's only used for local times that don't X ** specify a zone - those don't occur in email and netnews. X */ X#ifdef SYSV X tzset(); X gmtoff = -timezone; X#else /* SYSV */ X#ifdef BSD X gmtoff = now_tmP->tm_gmtoff; X#else /* BSD */ X /* You have to fill this in yourself. */ X gmtoff = !!!; X#endif /* BSD */ X#endif /* SYSV */ X X /* Skip initial whitespace ourselves - sscanf is clumsy at this. */ X for ( cp = str; *cp == ' ' || *cp == '\t'; ++cp ) X ; X X /* And do the sscanfs. WARNING: you can add more formats here, X ** but be careful! You can easily screw up the parsing of existing X ** formats when you add new ones. X */ X X /* N mth YYYY HH:MM:SS ampm zone */ X if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d %[apmAPM] %[^: ]", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec, X str_ampm, str_gmtoff ) == 8 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d %[^: ]", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec, X str_gmtoff ) == 7 ) && X scan_mon( str_mon, &tm_mon ) && X scan_gmtoff( str_gmtoff, &gmtoff ) ) X { X DP( "N mth YYYY HH:MM:SS ampm zone" ); X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X got_zone = 1; X } X /* N mth YYYY HH:MM ampm zone */ X else if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d %[apmAPM] %[^: ]", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, str_ampm, X str_gmtoff ) == 7 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d %[a-zA-Z] %d %d:%d %[^: ]", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X str_gmtoff ) == 6 ) && X scan_mon( str_mon, &tm_mon ) && X scan_gmtoff( str_gmtoff, &gmtoff ) ) X { X DP( "N mth YYYY HH:MM ampm zone" ); X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X got_zone = 1; X } X /* N mth YYYY HH:MM:SS ampm */ X else if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d %[apmAPM]", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, &tm_sec, X str_ampm ) == 7 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d %[a-zA-Z] %d %d:%d:%d", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X &tm_sec ) == 6 ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "N mth YYYY HH:MM:SS ampm" ); X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X } X /* N mth YYYY HH:MM ampm */ X else if ( ( ( sscanf( cp, "%d %[a-zA-Z] %d %d:%d %[apmAPM]", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X str_ampm ) == 6 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d %[a-zA-Z] %d %d:%d", X &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min ) == 5 ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "N mth YYYY HH:MM ampm" ); X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X } X /* HH:MM:SS ampm zone N mth YYYY */ X else if ( ( ( sscanf( cp, "%d:%d:%d %[apmAPM] %[^: ] %d %[a-zA-Z] %d", X &tm_hour, &tm_min, &tm_sec, str_ampm, str_gmtoff, &tm_mday, X str_mon, &tm_year ) == 8 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d:%d:%d %[^: ] %d %[a-zA-Z] %d", X &tm_hour, &tm_min, &tm_sec, str_gmtoff, &tm_mday, str_mon, X &tm_year ) == 7 ) && X scan_gmtoff( str_gmtoff, &gmtoff ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "HH:MM:SS ampm zone N mth YYYY" ); X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X } X /* HH:MM ampm zone N mth YYYY */ X else if ( ( ( sscanf( cp, "%d:%d %[apmAPM] %[^: ] %d %[a-zA-Z] %d", X &tm_hour, &tm_min, str_ampm, str_gmtoff, &tm_mday, str_mon, X &tm_year ) == 7 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d:%d %[^: ] %d %[a-zA-Z] %d", X &tm_hour, &tm_min, str_gmtoff, &tm_mday, str_mon, X &tm_year ) == 6 ) && X scan_gmtoff( str_gmtoff, &gmtoff ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "HH:MM ampm N mth YYYY" ); X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X } X /* HH:MM:SS ampm N mth YYYY */ X else if ( ( ( sscanf( cp, "%d:%d:%d %[apmAPM] %d %[a-zA-Z] %d", X &tm_hour, &tm_min, &tm_sec, str_ampm, &tm_mday, str_mon, X &tm_year ) == 7 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d:%d:%d %d %[a-zA-Z] %d", X &tm_hour, &tm_min, &tm_sec, &tm_mday, str_mon, X &tm_year ) == 6 ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "HH:MM:SS ampm N mth YYYY" ); X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X } X /* HH:MM ampm N mth YYYY */ X else if ( ( ( sscanf( cp, "%d:%d %[apmAPM] %d %[a-zA-Z] %d", X &tm_hour, &tm_min, str_ampm, &tm_mday, str_mon, X &tm_year ) == 6 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d:%d %d %[a-zA-Z] %d", X &tm_hour, &tm_min, &tm_mday, str_mon, &tm_year ) == 5 ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "HH:MM ampm N mth YYYY" ); X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X } X /* wdy, N mth YYYY HH:MM:SS ampm zone */ X else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d %[apmAPM] %[^: ]", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X &tm_sec, str_ampm, str_gmtoff ) == 9 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d %[^: ]", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X &tm_sec, str_gmtoff ) == 8 ) && X scan_wday( str_wday, &tm_wday ) && X scan_mon( str_mon, &tm_mon ) && X scan_gmtoff( str_gmtoff, &gmtoff ) ) X { X DP( "wdy, N mth YYYY HH:MM:SS ampm zone" ); X tm.tm_wday = tm_wday; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X got_zone = 1; X } X /* wdy, N mth YYYY HH:MM ampm zone */ X else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d %[apmAPM] %[^: ]", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X str_ampm, str_gmtoff ) == 8 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d %[^: ]", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X str_gmtoff ) == 7 ) && X scan_wday( str_wday, &tm_wday ) && X scan_mon( str_mon, &tm_mon ) && X scan_gmtoff( str_gmtoff, &gmtoff ) ) X { X DP( "wdy, N mth YYYY HH:MM ampm zone" ); X tm.tm_wday = tm_wday; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X got_zone = 1; X } X /* wdy, N mth YYYY HH:MM:SS ampm */ X else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d %[apmAPM]", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X &tm_sec, str_ampm ) == 8 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d:%d", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X &tm_sec ) == 7 ) && X scan_wday( str_wday, &tm_wday ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "wdy, N mth YYYY HH:MM:SS ampm" ); X tm.tm_wday = tm_wday; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X } X /* wdy, N mth YYYY HH:MM ampm */ X else if ( ( ( sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d %[apmAPM]", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, &tm_min, X str_ampm ) == 7 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%[a-zA-Z], %d %[a-zA-Z] %d %d:%d", X str_wday, &tm_mday, str_mon, &tm_year, &tm_hour, X &tm_min ) == 6 ) && X scan_wday( str_wday, &tm_wday ) && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "wdy, N mth YYYY HH:MM ampm" ); X tm.tm_wday = tm_wday; X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X } X /* wdy mth N HH:MM:SS ampm zone YYYY */ X else if ( ( ( sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d:%d %[apmAPM] %[^: ] %d", X str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec, X str_ampm, str_gmtoff, &tm_year ) == 9 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d:%d %[^: ] %d", X str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec, X str_gmtoff, &tm_year ) == 8 ) && X scan_wday( str_wday, &tm_wday ) && X scan_mon( str_mon, &tm_mon ) && X scan_gmtoff( str_gmtoff, &gmtoff ) ) X { X DP( "wdy mth N HH:MM:SS ampm zone YYYY" ); X tm.tm_wday = tm_wday; X tm.tm_mon = tm_mon; X tm.tm_mday = tm_mday; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X got_zone = 1; X tm.tm_year = tm_year; X } X /* wdy mth N HH:MM ampm zone YYYY */ X else if ( ( ( sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d %[apmAPM] %[^: ] %d", X str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, X str_ampm, str_gmtoff, &tm_year ) == 8 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%[a-zA-Z] %[a-zA-Z] %d %d:%d %[^: ] %d", X str_wday, str_mon, &tm_mday, &tm_hour, &tm_min, X str_gmtoff, &tm_year ) == 7 ) && X scan_wday( str_wday, &tm_wday ) && X scan_mon( str_mon, &tm_mon ) && X scan_gmtoff( str_gmtoff, &gmtoff ) ) X { X DP( "wdy mth N HH:MM ampm zone YYYY" ); X tm.tm_wday = tm_wday; X tm.tm_mon = tm_mon; X tm.tm_mday = tm_mday; X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X got_zone = 1; X tm.tm_year = tm_year; X } X /* N mth YYYY */ X else if ( sscanf( cp, "%d %[a-zA-Z] %d", X &tm_mday, str_mon, &tm_year ) == 3 && X scan_mon( str_mon, &tm_mon ) ) X { X DP( "N mth YYYY" ); X tm.tm_mday = tm_mday; X tm.tm_mon = tm_mon; X tm.tm_year = tm_year; X tm.tm_hour = 0; X tm.tm_min = 0; X tm.tm_sec = 0; X } X /* HH:MM:SS ampm */ X else if ( ( sscanf( cp, "%d:%d:%d %[apmAPM]", X &tm_hour, &tm_min, &tm_sec, str_ampm ) == 4 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d:%d:%d", &tm_hour, &tm_min, &tm_sec ) == 3 ) X { X DP( "HH:MM:SS ampm" ); X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = tm_sec; X } X /* HH:MM ampm */ X else if ( ( sscanf( cp, "%d:%d %[apmAPM]", &tm_hour, &tm_min, X str_ampm ) == 3 && X scan_ampm( str_ampm, &m ) ) || X sscanf( cp, "%d:%d", &tm_hour, &tm_min ) == 2 ) X { X DP( "HH:MM" ); X tm.tm_hour = ampm_fix( tm_hour, ampm ); X tm.tm_min = tm_min; X tm.tm_sec = 0; X } X else X return (time_t) -1; X X if ( tm.tm_year > 1900 ) X tm.tm_year -= 1900; X else if ( tm.tm_year < 70 ) X tm.tm_year += 100; X X t = tm_to_time( &tm ); X t -= gmtoff; X if ( tm.tm_isdst && ! got_zone ) X t -= 60*60; X X return t; X } SHAR_EOF if test 19522 -ne "`wc -c < 'date_parse.c'`" then echo shar: error transmitting "'date_parse.c'" '(should have been 19522 characters)' fi fi # end of overwriting check echo shar: extracting "'date_sort.1'" '(784 characters)' if test -f 'date_sort.1' then echo shar: will not over-write existing file "'date_sort.1'" else sed 's/^X//' << \SHAR_EOF > 'date_sort.1' X.TH date_sort 1 "11 February 1995" X.SH NAME Xdate_sort - sort input by date X.SH SYNOPSIS X.B date_sort X.RI [ file X.IR ... ] X.SH DESCRIPTION X.PP XReads in lines from the input files or stdin. XThe lines should consist of or begin with dates. XSorts the lines and writes them out. X.SH "SEE ALSO" Xdate_order(1), deltime(1), xmit_time(1), date_parse(3) X.SH AUTHOR XCopyright (C) 1995 by Jef Poskanzer. X.\" Permission to use, copy, modify, and distribute this software and its X.\" documentation for any purpose and without fee is hereby granted, provided X.\" that the above copyright notice appear in all copies and that both that X.\" copyright notice and this permission notice appear in supporting X.\" documentation. This software is provided "as is" without express or X.\" implied warranty. SHAR_EOF if test 784 -ne "`wc -c < 'date_sort.1'`" then echo shar: error transmitting "'date_sort.1'" '(should have been 784 characters)' fi fi # end of overwriting check echo shar: extracting "'date_sort.c'" '(3085 characters)' if test -f 'date_sort.c' then echo shar: will not over-write existing file "'date_sort.c'" else sed 's/^X//' << \SHAR_EOF > 'date_sort.c' X/* date_sort - sort input by date X** X** Copyright (C) 1995 by Jef Poskanzer <jef@netcom.com>. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <string.h> X#include <malloc.h> X#include <time.h> X Xextern time_t date_parse(); X Xstatic void usage(); Xstatic void read_file(); Xstatic int line_compare(); Xstatic char* my_malloc(); Xstatic char* my_realloc(); Xstatic void out_of_mem(); X Xstatic char* argv0; X Xstruct line X { X char* text; X time_t date; X }; X Xstatic int maxlines, nlines; Xstatic struct line* lines; X Xvoid Xmain( argc, argv ) X int argc; X char* argv[]; X { X int argn; X FILE* f; X int i; X X argv0 = argv[0]; X argn = 1; X if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) X usage(); X X maxlines = 500; /* arbitrary initial value */ X lines = (struct line*) my_malloc( maxlines * sizeof(struct line) ); X nlines = 0; X X if ( argn == argc ) X read_file( stdin ); X else X while ( argn < argc ) X { X if ( strcmp( argv[argn], "-" ) == 0 ) X read_file( stdin ); X else X { X f = fopen( argv[argn], "r" ); X if ( f == (FILE*) 0 ) X { X perror( argv[argn] ); X exit( 1 ); X } X read_file( f ); X (void) fclose( f ); X } X ++argn; X } X X qsort( lines, nlines, sizeof(struct line), line_compare ); X X for ( i = 0; i < nlines; ++i ) X fputs( lines[i].text, stdout ); X X exit( 0 ); X } X Xstatic void Xusage() X { X (void) fprintf( stderr, "usage: %s [file ...]\n", argv0 ); X exit( 1 ); X } X Xstatic void Xread_file( f ) X FILE* f; X { X char aline[10000]; X X /* Read until end of file. */ X while ( fgets( aline, sizeof(aline), f ) != (char*) 0 ) X { X /* Make sure there's enough room in the lines array. */ X if ( nlines >= maxlines ) X { X maxlines *= 2; X lines = (struct line*) my_realloc( X (char*) lines, maxlines * sizeof(struct line) ); X } X lines[nlines].text = (char*) my_malloc( strlen( aline ) + 1 ); X (void) strcpy( lines[nlines].text, aline ); X lines[nlines].date = date_parse( aline ); X if ( lines[nlines].date == (time_t) -1 ) X (void) fprintf( stderr, "%s: unparsable date - %s", argv0, aline ); X ++nlines; X } X } X Xstatic int Xline_compare( l1, l2 ) X struct line* l1; X struct line* l2; X { X return l1->date - l2->date; X } X Xstatic char* Xmy_malloc( size ) X unsigned size; X { X char* r; X X r = malloc( size ); X if ( r == (char*) 0 ) X out_of_mem(); X return r; X } X Xstatic char* Xmy_realloc( p, size ) X char* p; X unsigned size; X { X char* r; X X r = realloc( p, size ); X if ( r == (char*) 0 ) X out_of_mem(); X return r; X } X Xstatic void Xout_of_mem() X { X (void) fprintf( stderr, "%s: out of memory\n", argv0 ); X exit( 1 ); X } SHAR_EOF if test 3085 -ne "`wc -c < 'date_sort.c'`" then echo shar: error transmitting "'date_sort.c'" '(should have been 3085 characters)' fi fi # end of overwriting check echo shar: extracting "'deltime.1'" '(978 characters)' if test -f 'deltime.1' then echo shar: will not over-write existing file "'deltime.1'" else sed 's/^X//' << \SHAR_EOF > 'deltime.1' X.TH deltime 1 "11 February 1995" X.SH NAME Xdeltime - show difference between two dates X.SH SYNOPSIS X.B deltime X.I date1 X.RI [ date2 ] X.SH DESCRIPTION X.PP XComputes the elapsed time between now and a Xspecified date/time, or between two specified date/times. XBe careful to put the dates in quotes if they contain spaces. XThe output format is dddd hh:mm:ss. X.PP XTimes earlier than 1970 cannot Xbe handled, because that's as far back as the internal Unix time format goes. X.SH "SEE ALSO" Xdate_sort(1), date_order(1), xmit_time(1), date_parse(3) X.SH AUTHOR XCopyright (C) 1995 by Jef Poskanzer. X.\" Permission to use, copy, modify, and distribute this software and its X.\" documentation for any purpose and without fee is hereby granted, provided X.\" that the above copyright notice appear in all copies and that both that X.\" copyright notice and this permission notice appear in supporting X.\" documentation. This software is provided "as is" without express or X.\" implied warranty. SHAR_EOF if test 978 -ne "`wc -c < 'deltime.1'`" then echo shar: error transmitting "'deltime.1'" '(should have been 978 characters)' fi fi # end of overwriting check echo shar: extracting "'deltime.c'" '(1932 characters)' if test -f 'deltime.c' then echo shar: will not over-write existing file "'deltime.c'" else sed 's/^X//' << \SHAR_EOF > 'deltime.c' X/* deltime - show difference between two dates X** X** Copyright (C) 1995 by Jef Poskanzer <jef@netcom.com>. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <time.h> X Xextern time_t date_parse(); X Xstatic void usage(); Xstatic void unparsable(); X Xstatic char* argv0; X X#define SECSPERMINUTE 60 X#define SECSPERHOUR (60 * SECSPERMINUTE) X#define SECSPERDAY (24 * SECSPERHOUR) X Xvoid Xmain( argc, argv ) X int argc; X char* argv[]; X { X time_t t1, t2; X long delta; X int days, hours, minutes, secs; X X argv0 = argv[0]; X X if ( argc == 2 ) X { X t1 = date_parse( argv[1] ); X if ( t1 == (time_t) -1 ) X unparsable( argv[1] ); X t2 = time( (time_t*) 0 ); X } X else if ( argc == 3 ) X { X t1 = date_parse( argv[1] ); X if ( t1 == (time_t) -1 ) X unparsable( argv[1] ); X t2 = date_parse( argv[2] ); X if ( t2 == (time_t) -1 ) X unparsable( argv[2] ); X } X else X usage(); X X delta = t2 - t1; X if ( delta < 0 ) X { X (void) printf( "-" ); X delta = -delta; X } X X days = delta / SECSPERDAY; X delta = delta - days * SECSPERDAY; X hours = delta / SECSPERHOUR; X delta = delta - hours * SECSPERHOUR; X minutes = delta / SECSPERMINUTE; X delta = delta - minutes * SECSPERMINUTE; X secs = delta; X X printf( "%d %2d:%02d:%02d\n", days, hours, minutes, secs ); X X exit( 0 ); X } X Xstatic void Xusage() X { X (void) fprintf( stderr, "usage: %s date1 [date2]\n", argv0 ); X exit( 1 ); X } X Xstatic void Xunparsable( str ) X char* str; X { X (void) fprintf( stderr, "%s: unparsable date - %s\n", argv0, str ); X exit( 1 ); X } SHAR_EOF if test 1932 -ne "`wc -c < 'deltime.c'`" then echo shar: error transmitting "'deltime.c'" '(should have been 1932 characters)' fi fi # end of overwriting check echo shar: extracting "'dptest.c'" '(286 characters)' if test -f 'dptest.c' then echo shar: will not over-write existing file "'dptest.c'" else sed 's/^X//' << \SHAR_EOF > 'dptest.c' X#include <sys/types.h> X#include <stdio.h> X#include <time.h> X Xextern time_t date_parse(); X Xmain( argc, argv ) X int argc; X char* argv; X { X char line[5000]; X X while ( gets( line ) != (char*) 0 ) X (void) printf( "%s - %d\n", line, date_parse( line ) ); X X exit( 0 ); X } SHAR_EOF if test 286 -ne "`wc -c < 'dptest.c'`" then echo shar: error transmitting "'dptest.c'" '(should have been 286 characters)' fi fi # end of overwriting check echo shar: extracting "'test_input'" '(4336 characters)' if test -f 'test_input' then echo shar: will not over-write existing file "'test_input'" else sed 's/^X//' << \SHAR_EOF > 'test_input' X6 Feb 1995 09:00:00 AM PST X6 Feb 1995 09:00:00 PST X6 Feb 1995 09:00 AM PST X6 Feb 1995 09:00 PST X6 Feb 1995 09:00:00 AM X6 Feb 1995 09:00:00 X6 Feb 1995 09:00 AM X6 Feb 1995 09:00 X09:00:00 AM PST 6 Feb 1995 X09:00:00 PST 6 Feb 1995 X09:00 AM PST 6 Feb 1995 X09:00 PST 6 Feb 1995 X09:00:00 AM 6 Feb 1995 X09:00:00 6 Feb 1995 X09:00 AM 6 Feb 1995 X09:00 6 Feb 1995 XMon, 6 Feb 1995 09:00:00 AM PST XMon, 6 Feb 1995 09:00:00 PST XMon, 6 Feb 1995 09:00 AM PST XMon, 6 Feb 1995 09:00 PST XMon, 6 Feb 1995 09:00:00 AM XMon, 6 Feb 1995 09:00:00 XMon, 6 Feb 1995 09:00 AM XMon, 6 Feb 1995 09:00 XMon Feb 6 09:00:00 AM PST 1995 XMon Feb 6 09:00:00 PST 1995 XMon Feb 6 09:00 AM PST 1995 XMon Feb 6 09:00 PST 1995 XMon, 6 Feb 1995 09:00:00 AM PST XMon, 6 Feb 1995 09:00:00 PM PST XSun, 6 Feb 1995 09:00:00 PST XSunday, 6 Feb 1995 09:00:00 PST XMon, 6 Feb 1995 09:00:00 PST XMonday, 6 Feb 1995 09:00:00 PST XTue, 6 Feb 1995 09:00:00 PST XTuesday, 6 Feb 1995 09:00:00 PST XWed, 6 Feb 1995 09:00:00 PST XWednesday, 6 Feb 1995 09:00:00 PST XThu, 6 Feb 1995 09:00:00 PST XThursday, 6 Feb 1995 09:00:00 PST XFri, 6 Feb 1995 09:00:00 PST XFriday, 6 Feb 1995 09:00:00 PST XSat, 6 Feb 1995 09:00:00 PST XSaturday, 6 Feb 1995 09:00:00 PST XMon, 6 Jan 1995 09:00:00 PST XMon, 6 January 1995 09:00:00 PST XMon, 6 Feb 1995 09:00:00 PST XMon, 6 February 1995 09:00:00 PST XMon, 6 Mar 1995 09:00:00 PST XMon, 6 March 1995 09:00:00 PST XMon, 6 Apr 1995 09:00:00 PST XMon, 6 April 1995 09:00:00 PST XMon, 6 May 1995 09:00:00 PST XMon, 6 Jun 1995 09:00:00 PST XMon, 6 June 1995 09:00:00 PST XMon, 6 Jul 1995 09:00:00 PST XMon, 6 July 1995 09:00:00 PST XMon, 6 Aug 1995 09:00:00 PST XMon, 6 August 1995 09:00:00 PST XMon, 6 Sep 1995 09:00:00 PST XMon, 6 September 1995 09:00:00 PST XMon, 6 Oct 1995 09:00:00 PST XMon, 6 October 1995 09:00:00 PST XMon, 6 Nov 1995 09:00:00 PST XMon, 6 November 1995 09:00:00 PST XMon, 6 Dec 1995 09:00:00 PST XMon, 6 December 1995 09:00:00 PST XMon, 6 Feb 1995 09:00:00 GMT XMon, 6 Feb 1995 09:00:00 UTC XMon, 6 Feb 1995 09:00:00 UT XMon, 6 Feb 1995 09:00:00 0000 XMon, 6 Feb 1995 09:00:00 +0000 XMon, 6 Feb 1995 09:00:00 -0000 XMon, 6 Feb 1995 09:00:00 0100 XMon, 6 Feb 1995 09:00:00 +0100 XMon, 6 Feb 1995 09:00:00 -0100 XMon, 6 Feb 1995 09:00:00 0200 XMon, 6 Feb 1995 09:00:00 +0200 XMon, 6 Feb 1995 09:00:00 -0200 XMon, 6 Feb 1995 09:00:00 0300 XMon, 6 Feb 1995 09:00:00 +0300 XMon, 6 Feb 1995 09:00:00 -0300 XMon, 6 Feb 1995 09:00:00 0400 XMon, 6 Feb 1995 09:00:00 +0400 XMon, 6 Feb 1995 09:00:00 -0400 XMon, 6 Feb 1995 09:00:00 0500 XMon, 6 Feb 1995 09:00:00 +0500 XMon, 6 Feb 1995 09:00:00 -0500 XMon, 6 Feb 1995 09:00:00 0600 XMon, 6 Feb 1995 09:00:00 +0600 XMon, 6 Feb 1995 09:00:00 -0600 XMon, 6 Feb 1995 09:00:00 0700 XMon, 6 Feb 1995 09:00:00 +0700 XMon, 6 Feb 1995 09:00:00 -0700 XMon, 6 Feb 1995 09:00:00 0800 XMon, 6 Feb 1995 09:00:00 +0800 XMon, 6 Feb 1995 09:00:00 -0800 XMon, 6 Feb 1995 09:00:00 0900 XMon, 6 Feb 1995 09:00:00 +0900 XMon, 6 Feb 1995 09:00:00 -0900 XMon, 6 Feb 1995 09:00:00 1000 XMon, 6 Feb 1995 09:00:00 +1000 XMon, 6 Feb 1995 09:00:00 -1000 XMon, 6 Feb 1995 09:00:00 1100 XMon, 6 Feb 1995 09:00:00 +1100 XMon, 6 Feb 1995 09:00:00 -1100 XMon, 6 Feb 1995 09:00:00 1200 XMon, 6 Feb 1995 09:00:00 +1200 XMon, 6 Feb 1995 09:00:00 -1200 XMon, 6 Feb 1995 09:00:00 JST XMon, 6 Feb 1995 09:00:00 JDT XMon, 6 Feb 1995 09:00:00 BST XMon, 6 Feb 1995 09:00:00 NST XMon, 6 Feb 1995 09:00:00 AST XMon, 6 Feb 1995 09:00:00 EDT XMon, 6 Feb 1995 09:00:00 EST XMon, 6 Feb 1995 09:00:00 EDT XMon, 6 Feb 1995 09:00:00 CST XMon, 6 Feb 1995 09:00:00 CDT XMon, 6 Feb 1995 09:00:00 MST XMon, 6 Feb 1995 09:00:00 MDT XMon, 6 Feb 1995 09:00:00 PST XMon, 6 Feb 1995 09:00:00 PDT XMon, 6 Feb 1995 09:00:00 YST XMon, 6 Feb 1995 09:00:00 YDT XMon, 6 Feb 1995 09:00:00 HST XMon, 6 Feb 1995 09:00:00 HDT XMon, 6 Feb 1995 09:00:00 A XMon, 6 Feb 1995 09:00:00 B XMon, 6 Feb 1995 09:00:00 C XMon, 6 Feb 1995 09:00:00 D XMon, 6 Feb 1995 09:00:00 E XMon, 6 Feb 1995 09:00:00 F XMon, 6 Feb 1995 09:00:00 G XMon, 6 Feb 1995 09:00:00 H XMon, 6 Feb 1995 09:00:00 I XMon, 6 Feb 1995 09:00:00 K XMon, 6 Feb 1995 09:00:00 L XMon, 6 Feb 1995 09:00:00 M XMon, 6 Feb 1995 09:00:00 N XMon, 6 Feb 1995 09:00:00 O XMon, 6 Feb 1995 09:00:00 P XMon, 6 Feb 1995 09:00:00 Q XMon, 6 Feb 1995 09:00:00 R XMon, 6 Feb 1995 09:00:00 S XMon, 6 Feb 1995 09:00:00 T XMon, 6 Feb 1995 09:00:00 U XMon, 6 Feb 1995 09:00:00 V XMon, 6 Feb 1995 09:00:00 W XMon, 6 Feb 1995 09:00:00 X XMon, 6 Feb 1995 09:00:00 Y SHAR_EOF if test 4336 -ne "`wc -c < 'test_input'`" then echo shar: error transmitting "'test_input'" '(should have been 4336 characters)' fi fi # end of overwriting check echo shar: extracting "'test_output'" '(6148 characters)' if test -f 'test_output' then echo shar: will not over-write existing file "'test_output'" else sed 's/^X//' << \SHAR_EOF > 'test_output' X6 Feb 1995 09:00:00 AM PST - 792090000 X6 Feb 1995 09:00:00 PST - 792090000 X6 Feb 1995 09:00 AM PST - 792090000 X6 Feb 1995 09:00 PST - 792090000 X6 Feb 1995 09:00:00 AM - 792090000 X6 Feb 1995 09:00:00 - 792090000 X6 Feb 1995 09:00 AM - 792090000 X6 Feb 1995 09:00 - 792090000 X09:00:00 AM PST 6 Feb 1995 - 792090000 X09:00:00 PST 6 Feb 1995 - 792090000 X09:00 AM PST 6 Feb 1995 - 792090000 X09:00 PST 6 Feb 1995 - 792090000 X09:00:00 AM 6 Feb 1995 - 792090000 X09:00:00 6 Feb 1995 - 792090000 X09:00 AM 6 Feb 1995 - 792090000 X09:00 6 Feb 1995 - 792090000 XMon, 6 Feb 1995 09:00:00 AM PST - 792090000 XMon, 6 Feb 1995 09:00:00 PST - 792090000 XMon, 6 Feb 1995 09:00 AM PST - 792090000 XMon, 6 Feb 1995 09:00 PST - 792090000 XMon, 6 Feb 1995 09:00:00 AM - 792090000 XMon, 6 Feb 1995 09:00:00 - 792090000 XMon, 6 Feb 1995 09:00 AM - 792090000 XMon, 6 Feb 1995 09:00 - 792090000 XMon Feb 6 09:00:00 AM PST 1995 - 792090000 XMon Feb 6 09:00:00 PST 1995 - 792090000 XMon Feb 6 09:00 AM PST 1995 - 792090000 XMon Feb 6 09:00 PST 1995 - 792090000 XMon, 6 Feb 1995 09:00:00 AM PST - 792090000 XMon, 6 Feb 1995 09:00:00 PM PST - 792133200 XSun, 6 Feb 1995 09:00:00 PST - 792090000 XSunday, 6 Feb 1995 09:00:00 PST - 792090000 XMon, 6 Feb 1995 09:00:00 PST - 792090000 XMonday, 6 Feb 1995 09:00:00 PST - 792090000 XTue, 6 Feb 1995 09:00:00 PST - 792090000 XTuesday, 6 Feb 1995 09:00:00 PST - 792090000 XWed, 6 Feb 1995 09:00:00 PST - 792090000 XWednesday, 6 Feb 1995 09:00:00 PST - 792090000 XThu, 6 Feb 1995 09:00:00 PST - 792090000 XThursday, 6 Feb 1995 09:00:00 PST - 792090000 XFri, 6 Feb 1995 09:00:00 PST - 792090000 XFriday, 6 Feb 1995 09:00:00 PST - 792090000 XSat, 6 Feb 1995 09:00:00 PST - 792090000 XSaturday, 6 Feb 1995 09:00:00 PST - 792090000 XMon, 6 Jan 1995 09:00:00 PST - 789411600 XMon, 6 January 1995 09:00:00 PST - 789411600 XMon, 6 Feb 1995 09:00:00 PST - 792090000 XMon, 6 February 1995 09:00:00 PST - 792090000 XMon, 6 Mar 1995 09:00:00 PST - 794509200 XMon, 6 March 1995 09:00:00 PST - 794509200 XMon, 6 Apr 1995 09:00:00 PST - 797187600 XMon, 6 April 1995 09:00:00 PST - 797187600 XMon, 6 May 1995 09:00:00 PST - 799779600 XMon, 6 Jun 1995 09:00:00 PST - 802458000 XMon, 6 June 1995 09:00:00 PST - 802458000 XMon, 6 Jul 1995 09:00:00 PST - 805050000 XMon, 6 July 1995 09:00:00 PST - 805050000 XMon, 6 Aug 1995 09:00:00 PST - 807728400 XMon, 6 August 1995 09:00:00 PST - 807728400 XMon, 6 Sep 1995 09:00:00 PST - 810406800 XMon, 6 September 1995 09:00:00 PST - 810406800 XMon, 6 Oct 1995 09:00:00 PST - 812998800 XMon, 6 October 1995 09:00:00 PST - 812998800 XMon, 6 Nov 1995 09:00:00 PST - 815677200 XMon, 6 November 1995 09:00:00 PST - 815677200 XMon, 6 Dec 1995 09:00:00 PST - 818269200 XMon, 6 December 1995 09:00:00 PST - 818269200 XMon, 6 Feb 1995 09:00:00 GMT - 792061200 XMon, 6 Feb 1995 09:00:00 UTC - 792061200 XMon, 6 Feb 1995 09:00:00 UT - 792061200 XMon, 6 Feb 1995 09:00:00 0000 - 792061200 XMon, 6 Feb 1995 09:00:00 +0000 - 792061200 XMon, 6 Feb 1995 09:00:00 -0000 - 792061200 XMon, 6 Feb 1995 09:00:00 0100 - 792057600 XMon, 6 Feb 1995 09:00:00 +0100 - 792057600 XMon, 6 Feb 1995 09:00:00 -0100 - 792064800 XMon, 6 Feb 1995 09:00:00 0200 - 792054000 XMon, 6 Feb 1995 09:00:00 +0200 - 792054000 XMon, 6 Feb 1995 09:00:00 -0200 - 792068400 XMon, 6 Feb 1995 09:00:00 0300 - 792050400 XMon, 6 Feb 1995 09:00:00 +0300 - 792050400 XMon, 6 Feb 1995 09:00:00 -0300 - 792072000 XMon, 6 Feb 1995 09:00:00 0400 - 792046800 XMon, 6 Feb 1995 09:00:00 +0400 - 792046800 XMon, 6 Feb 1995 09:00:00 -0400 - 792075600 XMon, 6 Feb 1995 09:00:00 0500 - 792043200 XMon, 6 Feb 1995 09:00:00 +0500 - 792043200 XMon, 6 Feb 1995 09:00:00 -0500 - 792079200 XMon, 6 Feb 1995 09:00:00 0600 - 792039600 XMon, 6 Feb 1995 09:00:00 +0600 - 792039600 XMon, 6 Feb 1995 09:00:00 -0600 - 792082800 XMon, 6 Feb 1995 09:00:00 0700 - 792036000 XMon, 6 Feb 1995 09:00:00 +0700 - 792036000 XMon, 6 Feb 1995 09:00:00 -0700 - 792086400 XMon, 6 Feb 1995 09:00:00 0800 - 792032400 XMon, 6 Feb 1995 09:00:00 +0800 - 792032400 XMon, 6 Feb 1995 09:00:00 -0800 - 792090000 XMon, 6 Feb 1995 09:00:00 0900 - 792028800 XMon, 6 Feb 1995 09:00:00 +0900 - 792028800 XMon, 6 Feb 1995 09:00:00 -0900 - 792093600 XMon, 6 Feb 1995 09:00:00 1000 - 792025200 XMon, 6 Feb 1995 09:00:00 +1000 - 792025200 XMon, 6 Feb 1995 09:00:00 -1000 - 792097200 XMon, 6 Feb 1995 09:00:00 1100 - 792021600 XMon, 6 Feb 1995 09:00:00 +1100 - 792021600 XMon, 6 Feb 1995 09:00:00 -1100 - 792100800 XMon, 6 Feb 1995 09:00:00 1200 - 792018000 XMon, 6 Feb 1995 09:00:00 +1200 - 792018000 XMon, 6 Feb 1995 09:00:00 -1200 - 792104400 XMon, 6 Feb 1995 09:00:00 JST - 792054000 XMon, 6 Feb 1995 09:00:00 JDT - 792050400 XMon, 6 Feb 1995 09:00:00 BST - 792064800 XMon, 6 Feb 1995 09:00:00 NST - 792073800 XMon, 6 Feb 1995 09:00:00 AST - 792075600 XMon, 6 Feb 1995 09:00:00 EDT - 792072000 XMon, 6 Feb 1995 09:00:00 EST - 792079200 XMon, 6 Feb 1995 09:00:00 EDT - 792072000 XMon, 6 Feb 1995 09:00:00 CST - 792082800 XMon, 6 Feb 1995 09:00:00 CDT - 792079200 XMon, 6 Feb 1995 09:00:00 MST - 792086400 XMon, 6 Feb 1995 09:00:00 MDT - 792082800 XMon, 6 Feb 1995 09:00:00 PST - 792090000 XMon, 6 Feb 1995 09:00:00 PDT - 792086400 XMon, 6 Feb 1995 09:00:00 YST - 792093600 XMon, 6 Feb 1995 09:00:00 YDT - 792090000 XMon, 6 Feb 1995 09:00:00 HST - 792097200 XMon, 6 Feb 1995 09:00:00 HDT - 792093600 XMon, 6 Feb 1995 09:00:00 A - 792064800 XMon, 6 Feb 1995 09:00:00 B - 792068400 XMon, 6 Feb 1995 09:00:00 C - 792072000 XMon, 6 Feb 1995 09:00:00 D - 792075600 XMon, 6 Feb 1995 09:00:00 E - 792079200 XMon, 6 Feb 1995 09:00:00 F - 792082800 XMon, 6 Feb 1995 09:00:00 G - 792086400 XMon, 6 Feb 1995 09:00:00 H - 792090000 XMon, 6 Feb 1995 09:00:00 I - 792093600 XMon, 6 Feb 1995 09:00:00 K - 792097200 XMon, 6 Feb 1995 09:00:00 L - 792100800 XMon, 6 Feb 1995 09:00:00 M - 792104400 XMon, 6 Feb 1995 09:00:00 N - 792064800 XMon, 6 Feb 1995 09:00:00 O - 792068400 XMon, 6 Feb 1995 09:00:00 P - 792072000 XMon, 6 Feb 1995 09:00:00 Q - 792075600 XMon, 6 Feb 1995 09:00:00 R - 792079200 XMon, 6 Feb 1995 09:00:00 S - 792082800 XMon, 6 Feb 1995 09:00:00 T - 792086400 XMon, 6 Feb 1995 09:00:00 U - 792090000 XMon, 6 Feb 1995 09:00:00 V - 792093600 XMon, 6 Feb 1995 09:00:00 W - 792097200 XMon, 6 Feb 1995 09:00:00 X - 792100800 XMon, 6 Feb 1995 09:00:00 Y - 792104400 SHAR_EOF if test 6148 -ne "`wc -c < 'test_output'`" then echo shar: error transmitting "'test_output'" '(should have been 6148 characters)' fi fi # end of overwriting check echo shar: extracting "'xmit_time.1'" '(989 characters)' if test -f 'xmit_time.1' then echo shar: will not over-write existing file "'xmit_time.1'" else sed 's/^X//' << \SHAR_EOF > 'xmit_time.1' X.TH xmit_time 1 "11 February 1995" X.SH NAME Xxmit_time - figure transmission time of netnews articles X.SH SYNOPSIS X.B xmit_time X.IR file ... X.SH DESCRIPTION X.PP XGiven a set of netnews article filenames as arguments, looks in each file for Xa netnews-format Date: line. XAlso looks at the last-modified time of the file. XThe difference between the two is how long it took that article to Xtravel from the poster's site to your site, and that number (in seconds) Xis written to stdout. X.SH "SEE ALSO" Xdate_sort(1), date_order(1), deltime(1), date_parse(3) X.SH AUTHOR XCopyright (C) 1995 by Jef Poskanzer. X.\" Permission to use, copy, modify, and distribute this software and its X.\" documentation for any purpose and without fee is hereby granted, provided X.\" that the above copyright notice appear in all copies and that both that X.\" copyright notice and this permission notice appear in supporting X.\" documentation. This software is provided "as is" without express or X.\" implied warranty. SHAR_EOF if test 989 -ne "`wc -c < 'xmit_time.1'`" then echo shar: error transmitting "'xmit_time.1'" '(should have been 989 characters)' fi fi # end of overwriting check echo shar: extracting "'xmit_time.c'" '(1975 characters)' if test -f 'xmit_time.c' then echo shar: will not over-write existing file "'xmit_time.c'" else sed 's/^X//' << \SHAR_EOF > 'xmit_time.c' X/* xmit_time - figure out transmission time of netnews articles X** X** Copyright (C) 1995 by Jef Poskanzer <jef@netcom.com>. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include <stdio.h> X#include <string.h> X#include <sys/stat.h> X#include <time.h> X Xextern time_t date_parse(); X Xstatic void usage(); Xstatic void do_file(); X Xstatic char* argv0; X Xvoid Xmain( argc, argv ) X int argc; X char* argv[]; X { X int argn; X X argv0 = argv[0]; X argn = 1; X if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) X usage(); X X while ( argn < argc ) X { X do_file( argv[argn] ); X ++argn; X } X X exit( 0 ); X } X Xstatic void Xusage() X { X (void) fprintf( stderr, "usage: %s file ...\n", argv0 ); X exit( 1 ); X } X Xstatic void Xdo_file( name ) X char* name; X { X struct stat sb; X time_t posted, arrived; X FILE* f; X char line[30000]; X X f = fopen( name, "r" ); X if ( f == (FILE*) 0 ) X { X perror( name ); X return; X } X X if ( fstat( fileno( f ), &sb ) < 0 ) X { X perror( name ); X (void) fclose( f ); X return; X } X arrived = sb.st_mtime; X X for (;;) X { X if ( fgets( line, sizeof(line), f ) == (char*) 0 ) X break; X if ( line[0] == '\n' ) X break; X if ( strncmp( line, "Date:", 5 ) == 0 ) X { X (void) fclose( f ); X posted = date_parse( &line[5] ); X if ( posted == (time_t) -1 ) X (void) fprintf( X stderr, "%s: unparsable date in %s - %s", X argv0, name, &line[5] ); X else X (void) printf( "%d\n", arrived - posted ); X return; X } X } X X (void) fprintf( stderr, "%s: no Date: line found in %s\n", argv0, name ); X (void) fclose( f ); X } X X SHAR_EOF if test 1975 -ne "`wc -c < 'xmit_time.c'`" then echo shar: error transmitting "'xmit_time.c'" '(should have been 1975 characters)' fi fi # end of overwriting check # End of shell archive exit 0
participants (1)
-
Monty Solomon