signals and stat()

Script started on Thu May 01 14:36:30 1997
sh-2.00$ 
sh-2.00$ cat track.c
/* track.c
	When SIGUSR1 is received by this program, it determines
	whether atime has changed for any of its arguments. This
	includes determining if the file cannot be stat'ed. Should
	run in the background.
*/

#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>


time_t get_atime(char *);
void restat(int);

time_t * atimes;	/* array to hold old atimes from previous round. */
int nargs;		/* Make argc and argv visible to interrupt handler. */
char ** argvcopy;


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

	/* Turn off signal of interest until we set up. */
	signal( SIGUSR1, SIG_IGN);

	/* Simple argument check */
	if( argc < 2 )
	{
		fprintf(stderr, "Usage: track file1 file2 ...\n");
		exit(1);
	}

	/* Let interrupt handler be able to see both argc and argv. */
	nargs = argc;
	argvcopy = argv;

	/* Do initial stats of the files */
	atimes = (time_t *) malloc ( (argc - 1)* sizeof(time_t) );
	for ( i = 0; i < argc - 1; i++ )
		atimes[i] = get_atime(argv[i+1]);

	/* Now set to trap signal. */
	signal( SIGUSR1, restat );

	/* Just wait for signal. */
	while( 1 )
		pause();
}

time_t get_atime(char * file)
{
	/* Return is -1 if we cannot stat the argument, st_atime otherwise. */
	struct stat buffer;
	return ( stat(file, &buffer) < 0) ? (time_t) -1 : buffer.st_atime;
}

void restat(int sig)
{
	int i;
	time_t newtime;

	/* If atime has changed, or we could stat the file before but
	   can't now, report it and change atime[] entry for this file.
	*/
	for (i = 0; i < nargs - 1; i++ )
		if( (newtime = get_atime(argvcopy[i+1])) != atimes[i] )
		{
			if( newtime == -1 )
				printf("No stat for %s\n", argvcopy[i+1]);
			else
				printf("New atime for %s\n", argvcopy[i+1]);
			atimes[i] = newtime;
		}
	/* In-class exercise: what's wrong with this? */
}

sh-2.00$ track foo junk &
[1] 20453
sh-2.00$ kill -SIGUSR1 20453
sh-2.00$ cat foo

sh-2.00$ kill -SIGUSR1 20453
New atime for foo
sh-2.00$ touch foo junk
sh-2.00$ kill -SIGUSR1 20453
New atime for foo
New atime for junk
sh-2.00$ rm foo
sh-2.00$ kill -SIGUSR1 20453
No stat for foo
sh-2.00$ kill 20453
[1]+  Terminated              track foo junk

sh-2.00$ exit
exit

script done on Thu May 01 14:40:09 1997