From: weigand@pecan.cns.udel.edu (Steve Weigand)
Subject: Logon detection
Reply-To: weigand@pecan.cns.udel.edu
Organization: University of Delaware, Newark
Date: Fri, 2 Oct 1992 01:57:35 GMT

My previous attempts to upload this program to comp.sources.unix and
comp.sources.misc have been failures, so I'm just going to upload it
directly to here.

Summary:  waituser is a program which I created that will allow one to
 wait until until a certain user logs into the machine you are currently
 logged in on.

 USAGE: waituser <username>

 It accomplishes this by repeatedly scanning the utmp file for any changes
 that happen to it. If the file is changed, waituser will recheck it to
 see if that user logged in. If not, it just keeps waiting for changes. 

 Obviously, infinite loops like this tend to take up lots of processor 
 time, but scanning for changes to a file, rather than scanning the entire
 file, should reduce most of the overhead. The result is a program which
 eats up a little, but not a lot, of processor time.

 Example:

	Suppose you had a friend with username "jdoe", who logs into your
	machine on occassion. You want to surprise him with a message the
	very instant he logs in. How 'bout a really big message (banner)
	to his screen? Here's what you'd do:

	Create the following shell script file using vi, calling it
	"test.scr":
		waituser jdoe
		banner Hi there John | write jdoe

	Now, run this program in the background before you logout by doing
	the following from your shell prompt:
		source test.scr &

	The ampersand will tell it to run in the background; so it will
	continue to be there even when you logout.

	When John Doe logs into his account, he should instantly see 
	a huge message on his screen, "Hi there John", even before seeing
	anything in his .login (it should be that fast!).

I release this program public domain. I don't care what you all do to it,
and I don't care if I am given credit. However, if you do find a way to
do it better, without taking up processor time, please post it.

Thanx, 
 -Steve Weigand
 (weigand@ee.udel.edu)

=============================CUT HERE====================================
/* Program: waituser.c 
** Author : Steven Weigand (weigand@ee.udel.edu)
** Date   : September 22, 1992
** Ver.   : 1.0
** Descr. :
**		This program will wait until the username you give it is
**		logged onto the system. The INSTANT that user logs in, this
**		program will exit, returning control back to your process.
**		The purpose of such a program is obvious, so I won't say
**		too much more on the subject. 
**
**		Reason for its invention: I didn't like constantly scanning
**	 	'users' for a certain names... when I did, it used up lots
**		of processor time, especially when the intervals between 
**		scans was small. This program will scan the /etc/utmp file
**		for the user in question. It will do this by checking it
**		for when the computer updates it, and then checking the 
**		list for the user you want. 
**
**		Example: 
**		 If you wanted to write your friend (weigand) a "hello" to
**		 his screen when he logged in, then create a script called
**		 "hiweigand" and make it executeable:
**			waituser weigand
**			banner Hello | write weigand
**		 When you activate this script, do so by using the & sign to
**		 make it run in the background, even after you've left:
**		 	hiweigand& 
**		 4 some odd hours/days later, your friend signs on and sees
**		 a big Hello on his screen. Nifty, huh?
**
** USAGE:	waituser username
*/
#include <stdio.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/stat.h>

#define EQ(a,b)  (strcmp(a,b) == 0)
char* sformat();

void main(i,v)
int i;
char** v;
{
 FILE* fp = NULL;
 struct utmp * UT = NULL;
 char* buffer = NULL;
 long counter = 0L;
 long index = 0L;
 char c;
 int endflag = 0;
 time_t cur_date = 0;
 struct stat stbufr;

 if (i<2) exit(-1);
 if (i>2) printf("Extra input ignored.\n");

while(!endflag)
{

 fp = fopen("/etc/utmp","r");
 fseek(fp,0L,2);

 if (fp == NULL) endflag = 1;

 if (fp != NULL)
 {
   buffer = (char*)malloc(ftell(fp)*sizeof(char));
   fseek(fp,0L,0);
   counter = 0L;
   index = 0L; 
   while (!feof(fp))
     buffer[counter++] = fgetc(fp); 
   UT = (struct utmp*)buffer;

   while (index < counter)
   {
        if (EQ(sformat(UT->ut_name,8),v[1]))
		  exit(0);
    	index = index + sizeof(struct utmp);
        UT++;
   } 
   free(buffer);
  
 } /*End if*/
 fclose(fp);
 /* Now, wait until /etc/utmp is changed */

 cur_date = stbufr.st_mtime;
 while(stbufr.st_mtime == cur_date)
	stat("/etc/utmp",&stbufr);
  /*It might take a lot of processor time, but this is better than opening
  **up the file and rechecking it every 1 millisecond! */


}/*End while*/
}/*End main()*/

char* sformat(s,l)
char* s;
int l;
{
 /* Will return a string of l characters long from s*/
 char* newstring;
 int counter = 0;

 newstring = (char*)malloc((l+1)*sizeof(char));

 for (counter=0;counter<l;counter++)
   newstring[counter] = s[counter];
 newstring[counter] = '\0';
 return newstring;
}
Newsgroups: comp.unix.questions