Cover V01, I02
Article
Listing 1

jul92.tar


Listing 1: older.c

#ifndef lint
static char sccsid[]="%Z%%M% %I% %E% %U% %Q%";
#endif

/*  OLDER.C


*
*  The Unix find command has no option that tells if a file is older
*  than a certain time less than one day.  It has a -newer option for
*  comparing one file's date against all the others, but not an -older
*  option.
*
*  Here's the original problem:  A bunch of files have come in
*  through uucp, collected in a subdir in the uucppublic dir.  Files
*  of this sort can be coming in at any time.  At a certain time of
*  the day, a cron job wakes up and wants to move the files already
*  arrived to another dir for further processing.  It mustn't move
*  all the files in the subdir since a new one could be coming in at
*  the very time the mv is requested by cron.  We don't want the
*  partial file in transit moved.  So, we need all files older than,
*  say, 15 minutes prior to the current system time to be moved.
*  That should be sufficient to capture the filenames prior to the
*  one still in transit.
*
*  For future application, this program will take a command line
*  parameter specifying the actual number of minutes to use prior to
*  the current system time, and a list of directories.  If no time is
*  given, 15 minutes will be presumed.  If no directories are given,
*  the '.' dir will be presumed.  The program will write all matching
*  filenames to stdout.
*
*  Copyright 1992, by Lawrence S Reznick -- Feb 5, 1992
*/

#include    <stdio.h>
#include    <stdlib.h>
#include    <string.h>
#include    <sys/types.h>
#include    <time.h>
#include    <dirent.h>
#include    <sys/stat.h>

/*
*  Prototypes
*/

extern int  stat(char *, struct stat *); /* SCO didn't prototype it */

static int  show_files(char *dirname, time_t start_time);

static time_t   reduce_time(int minutes);

/*
*  Constants
*/

#define FALSE   0
#define TRUE    1

/*
*  Macros
*/

#define FEBDAYS(year)   (((((year) % 400) == 0) || \
((((year) % 100) != 0) && (((year) & 3) == 0))) ? 29 : 28)

/*
*  Globals
*/

char    *progname;

/*
*  Statics
*/

/*
*  General Functions
*/

main(int argc, char *argv[])
{
int i,
err;

time_t  start_time;

progname = argv[0];         /* For errors */

if (argc > 1 && argv[1][0] == '-') {
fputs("Usage:\t", stderr);
fputs(progname, stderr);
fputs(" [minutes [dir ...]]\n\n", stderr);
fputs("Shows all filenames in the dir list older than the "
"number of minutes\nprior to the current time.  If "
"no minutes given, use 15.  If no dir\nlist given "
"use current dir.  Filenames are output to stdout.\n",
stderr);
exit(1);
}

if (argc < 2) {
start_time = reduce_time(15);   /* Reduce by std prior min */
}
else {
start_time = reduce_time(atoi(argv[1]));
}

if (argc < 3) {
show_files(".", start_time);
}
else {
err = FALSE;
for (i = 2; !err && i < argc; i++) {
err = show_files(argv[i], start_time);
}
}

return(0);
}

/*
*  Special Functions
*/

static time_t reduce_time(int min)
{
static int  day[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

int     minutes, hours, days;

time_t      now;        /* Current time */

struct tm   *t;     /* Use localtime()'s workspace */

now = time(NULL);
t = localtime(&now);        /* Convert for time arithmetic */

minutes = min % 60;
hours = (min /= 60) % 24;
days = min /= 24;

if ((t->tm_min -= minutes) < 0) {   /* Reduce minutes */
t->tm_min += 60;        /* 60 minutes/hour */
t->tm_hour--;
}

if ((t->tm_hour -= hours) < 0) {    /* Reduce hours */
t->tm_hour += 24;       /* 24 hours/day */
t->tm_mday--;
}

/* Days adjustment requires correspondence with the
* calendar.  Reduce the days by the day in the current
* month and then go back to the previous month (previous
* year if needed) until the number of days have been
* reduced to less than the time of one month.  That
* number of days gets taken away from the last day number
* of the adjusted month and becomes the actual calendar
* date.
*/

day[1] = FEBDAYS(t->tm_year);       /* Adjust February */

while (days > t->tm_mday) {     /* Still within this month? */
days -= t->tm_mday;     /* Reduce by this day number */
if (--t->tm_mon < 0) {      /* Correct for previous year */
t->tm_mon = 11;
t->tm_year--;
day[1] = FEBDAYS(t->tm_year);
}
t->tm_mday = day[t->tm_mon];    /* Use previous month */
}
t->tm_mday -= days;         /* Take days off the date */

return(mktime(t));          /* Return the earlier time */
}

static int show_files(char *dirname, time_t start_time)
{
char    pathname[256];      /* Full pathname of file */

int dirlen;

DIR *d;         /* Dir being examined */

struct dirent   *dp;        /* Directory structure */

struct stat statbuf;

if ((d = opendir(dirname)) == NULL) {
fputs(progname, stderr);
fputs(": Error opening dir ", stderr);
perror(dirname);
return(TRUE);
}

dirlen = strlen(dirname);
strcpy(pathname, dirname);
pathname[dirlen++] = '/';
pathname[dirlen] = '\0';

while ((dp = readdir(d)) != NULL) {
if (dp->d_name[0] != '.') { /* Skip ., .., & hidden files */
strcpy(pathname + dirlen, dp->d_name);

if (!stat(pathname, &statbuf) &&
difftime(start_time, statbuf.st_mtime) >= 0.0) {
puts(pathname);
}
}
}

closedir(d);

return(FALSE);
}