Daily Login Usage Restrictor
John F. Haugh II
jfh at rpp386.Dallas.TX.US
Mon Jul 31 04:57:55 AEST 1989
I whipped this up as it became apparent I might wind up with
my dial-up users getting busy signals because of each other.
How this works ...
You start by adding a line either to your users .profile or
to the system-wide startup file. The line should be of the
form
/etc/timer 3600
where 3600 is the number of seconds in an hour, or however
many minutes you want them to be logged in per day. I use
a four hour limit, so obviously I use something like
/etc/timer 14400
The /etc/timer program then notes whether or not it is being
exec'd by a login shell, as told by getpgrp() and goes off into
the background to hide.
Once a minute it checks for the existence of its parent and
updates its usage counters. When the daily usage reaches the
limit on the command line, out you go! It is smart enough
to detect multiple logins and charge for each in a cummulative
fashion [ which explains some of the goings on ]
The user is told their initial time remaining when they first
login, and is then warned at 10 minutes remaining and at each
minute between five and zero. If they choose to ignore your
warnings, it's SIGKILL for the kiddies!
Several clever methods of defeat have been checked for,
including forking the bugger into the background and leaving
init as the parent [ which would be real nasty, sending init
a SIGKILL ... ]
Let me know what you think, other than that I'm a fascist
bastard. Included is timer.c, which should be compiled to
become /etc/timer, mode 4711 owner root, and usage.c which
should be compiled to become /etc/usage, mode 700, owner
root. [ or mode 4711 to allow users to check on their own
usage ]
Documentation? Ha! Read the source you luser!
--
#! /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:
# timer.c
# usage.c
# This archive created: Sun Jul 30 13:55:37 1989
# By: John F. Haugh II (River Parishes Programming, Plano TX)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'timer.c'
then
echo shar: "will not over-write existing file 'timer.c'"
else
cat << \SHAR_EOF > 'timer.c'
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#define TIMER_LOG "/usr/adm/timer"
#define INTERVAL 60
struct timer {
long today;
long usage;
};
void update_usage();
void print_remaining();
main (argc, argv)
int argc;
char **argv;
{
char *cp;
int uid = getuid ();
int parent = getppid ();
int fd;
int minutes;
long usage;
long start;
long strtol();
struct timer timer;
void catch();
if (parent != getpgrp () || parent <= 1 || argc != 2)
exit (1);
usage = strtol (argv[1], &cp, 10);
if (cp == argv[1])
exit (2);
if ((fd = open (TIMER_LOG, O_RDWR|O_CREAT, 0600)) < 0)
exit (3);
(void) lseek (fd, (long) uid * sizeof timer, 0);
if (read (fd, &timer, sizeof timer) != sizeof timer)
memset (&timer, 0, sizeof timer);
(void) time (&start);
update_usage (fd, &timer, uid, 0);
print_remaining (usage - timer.usage);
if (usage - timer.usage <= 0)
kill (- parent, SIGKILL);
signal (SIGHUP, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
signal (SIGTERM, SIG_IGN);
if (fork () != 0)
exit (0);
setpgrp ();
setuid (geteuid ());
while (usage > timer.usage) {
sleep (INTERVAL);
if (kill (parent, 0) == -1)
exit (0);
update_usage (fd, &timer, uid, INTERVAL);
minutes = (usage - timer.usage) / 60;
if (minutes == 10 || minutes <= 5)
print_remaining (usage - timer.usage);
}
sleep (15);
kill (- parent, SIGKILL);
}
void
update_usage (fd, timer, id, delta)
int fd;
struct timer *timer;
int id;
long delta;
{
long today = time (0) / (24*3600);
(void) lseek (fd, (long) id * sizeof *timer, 0);
if (read (fd, timer, sizeof *timer) != sizeof *timer)
memset (timer, 0, sizeof *timer);
if (today != timer->today) {
timer->today = today;
timer->usage = 0;
}
timer->usage += delta;
(void) lseek (fd, (long) id * sizeof *timer, 0);
(void) write (fd, timer, sizeof *timer);
}
void
print_remaining (remaining)
long remaining;
{
char buf[BUFSIZ];
int hours = remaining / 3600;
int minutes = (remaining % 3600) / 60;
if (remaining <= 60)
strcpy (buf, "no time");
else if (remaining < 3600)
sprintf (buf, "%d %s",
minutes, minutes != 1 ? "minutes":"minute");
else {
if (minutes == 0)
sprintf (buf, "%d %s",
hours, hours != 1 ? "hours":"hour");
else
sprintf (buf, "%d %s, %d %s",
hours, hours != 1 ? "hours":"hour",
minutes, minutes != 1 ? "minutes":"minute");
}
printf ("You have %s remaining.\n", buf);
}
SHAR_EOF
fi
if test -f 'usage.c'
then
echo shar: "will not over-write existing file 'usage.c'"
else
cat << \SHAR_EOF > 'usage.c'
#include <sys/types.h>
#include <pwd.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#define TIMER_LOG "/usr/adm/timer"
struct timer {
long today;
long usage;
};
print_usage (id, time)
int id;
long time;
{
int hours;
int minutes;
struct passwd *pwd;
hours = time / 3600;
minutes = (time % 3600) / 60;
if (pwd = getpwuid (id))
printf ("%8.8s %02d:%02d\n", pwd->pw_name, hours, minutes);
else
printf ("%8d %02d:%02d\n", id, hours, minutes);
}
main (argc, argv)
int argc;
char **argv;
{
int fd;
int uid;
int all = 0;
long today = time (0) / (24*3600L);
struct timer timer;
if (argc == 2 && strcmp (argv[1], "all") == 0)
all = 1;
if ((fd = open (TIMER_LOG, O_RDONLY)) < 0) {
perror (TIMER_LOG);
exit (1);
}
uid = 0;
while (read (fd, &timer, sizeof timer) == sizeof timer) {
if (timer.today == today || (timer.today && all))
print_usage (uid, timer.usage);
uid++;
}
}
SHAR_EOF
fi
exit 0
# End of shell archive
--
John F. Haugh II +-Quote of the month club: ------------
VoiceNet: (512) 832-8832 Data: -8835 | "Computer security is to information
InterNet: jfh at rpp386.cactus.org | control as a chastity belt is to
UucpNet : <backbone>!bigtex!rpp386!jfh +- birth control" -- Doug Steves --
More information about the Alt.sources
mailing list