AUSAM/source/S/ac1.c
#
/*
* ac [ [[-]f...]... ] [name]
*
* where 'f' is any of 'defhilnopstuwCILNPSU'
* and "name" is any extra string required by a flag 'f'.
*
* Piers Lauder Mar '78
*/
#include <local-system>
#ifdef AUSAM
#include "ac.h" /* for definitions of flags, data and include files */
#include <passwd.h>
#ifdef WTMP_AUTOLOCK
#include <stat16.h>
#endif WTMP_AUTOLOCK
char *wtmpf "/usr/adm/wtmp";
int wf; /* file descriptor for wtmp file */
static char noname[] "%s: no name for '%c' flag.\n";
#ifdef DIAGNOSTIC_REDIRECT
char *diagf "ac.diagnostics";
#endif
/*
* the main program - deal with parameters, set up files, call ac()
*/
main( argc, argv )
register argc;
register char **argv;
{
register c;
extern fout;
extern char *etcpasswd;
fout = 2; /* for errors */
name = *argv++; /* invoked name */
while ( --argc )
{
while ( c = *(*argv)++ )
switch ( c )
{
case '-': continue;
case 'I': flg.I++; continue;
case 'P': flg.P++; continue;
case 'd': flg.d++; continue;
case 'e': flg.e++; continue;
case 'f': flg.f++; continue;
case 'h': flg.h++; continue;
case 'i': flg.z++; continue;
case 'l': flg.l++; continue;
case 'n': flg.n++; continue;
case 'o': flg.o++; continue;
case 'p': flg.p++; continue;
case 's': flg.s++; continue;
case 't': flg.t++; continue;
case 'u': flg.u++; continue;
case 'w': flg.w++; continue;
# ifdef DIAGNOSTIC_REDIRECT
case 'x': flg.x++; continue;
# endif
# ifdef DEBUG|TIME_TRACE
case 'y': flg.y++; continue;
# endif
case 'C': porder = bycpu; continue;
case 'L': porder = bylog; continue;
case 'N': porder = byname; continue;
case 'S': porder = bylogons; continue;
case 'U': porder = byuid; continue;
default:
printf( "%s: bad flag '%c',\n", name, c );
continue;
}
argv++;
if ( flg.w )
if ( --argc )
{
wtmpf = *argv++;
flg.w = 0;
}
else
{
printf( noname, name, 'w' );
return( 1 );
}
if ( flg.P )
if ( --argc )
{
if ( flg.i )
{
printf( "%s: 'P' should precede 'i'\n", name );
return( 1 );
}
pwfile( *argv++ );
flg.P = 0;
}
else
{
printf( noname, name, 'P' );
return( 1 );
}
if ( flg.z )
if ( --argc )
{
struct pwent pe;
pe.pw_strings[LNAME] = *argv++;
if ( getpwuid( &pe, 0, 0 ) < 0 )
{
printf( "%s: who is \"%s\"?\n", name, pe.pw_strings[LNAME] );
return( 1 );
}
if ( !flg.i )
{
individual = pe.pw_uid;
flg.i++; flg.p++; flg.n++;
}
else
printf( "%s: only one individual allowed, %s ignored\n", name, pe.pw_strings[LNAME] );
flg.z = 0;
}
else
{
printf( noname, name, 'i' );
return( 1 );
}
if ( flg.l )
if ( --argc )
{
w_days_lost = atoi( *argv++ );
flg.l = 0;
}
else
{
printf( noname, name, 'l' );
return( 1 );
}
}
if ( !flg.I && (wf = open( wtmpf, 0 )) < 0 )
{
printf( "%s: cannot open %s!\n", name, wtmpf );
return( 1 );
}
# ifdef WTMP_AUTOLOCK
if ( !flg.I )
{
struct statbuf buf;
fstat( wf, &buf );
if ( buf.sb_flags & IFLOCK )
{
unlock();
flg.locking++;
}
}
# endif WTMP_AUTOLOCK
if ( flg.d && w_days_lost )
{
printf( "%s: working days lost ignored!\n" );
w_days_lost = 0;
}
fout = dup( 1 );
# ifdef DIAGNOSTIC_REDIRECT
if ( flg.x )
{
close( 2 );
if ( open( diagf, 1 ) < 0 )
{
if ( creat( diagf, 0600 ) < 0 )
{
printf( "%s: cannot create %s!\n", name, diagf );
return( -1 );
}
}
else
seek( 2, 0, 2 );
}
# endif
if ( !flg.I )
close( 0 );
close( 1 );
if ( !flg.e && !flg.h && !flg.i && !flg.p && !flg.s && !flg.t && !flg.u )
{
if ( individual = getreal() )
{
flg.i++; /* default individual if not root */
flg.p++;
}
else
flg.s++; /* default statistics */
# ifdef DIAGNOSTIC_REDIRECT
if ( !flg.x )
# endif DIAGNOSTIC_REDIRECT
flg.n++; /* with no warnings */
}
if ( flg.p && !porder )
porder = byname; /* default people sort order */
if ( flg.o )
printf( "\nNote: cpu times not available in pre-AUSAM accounts.\n" );
ac();
flush();
return( 0 );
}
struct wtmp wtmp[512/WTMPSIZ];
/*
* ac main loop to read accounting file and call appropriate accounting routines
* ==
*/
ac()
{
register struct wtmp *wp;
register n;
extern login(), logout(), async();
for ( ;; )
{
# ifdef WTMP_AUTOLOCK
if ( flg.locking )
readlock( wf );
# endif WTMP_AUTOLOCK
n = read( wf, (wp=wtmp), (sizeof wtmp) );
# ifdef WTMP_AUTOLOCK
if ( flg.locking )
unlock();
# endif WTMP_AUTOLOCK
if ( (n <= 0) || ((n =/ WTMPSIZ) == 0) )
break;
do
{
switch ( wp->w_type )
{
case U_TYPE: time( login, wp ); break;
case O_TYPE: time( logout, wp ); break;
case W_TYPE: time( async, wp ); break;
case S_TYPE: boot( wp ); break;
case D_TYPE: update( wp ); break;
case SU_TYPE: continue;
default:
warn( "unrecognised type ignored", wp );
continue;
}
}
while
( wp++ , --n );
}
if ( flg.z )
print( timenow );
}
/*
* time initialises and keeps trace of time
* ====
*/
time( f, wp )
int (*f)();
register struct wtmp *wp;
{
if ( wp->w_finishtime >= hour )
if ( flg.z )
chime( wp, 0 );
else
init( wp );
if ( wp->w_finishtime < timenow )
{
static long sometime;
if ( sometime != timenow && wp->w_finishtime < (timenow - MINUTE) )
{
warn( "date error", wp );
sometime = timenow;
}
if ( wp->w_finishtime == 0 )
{
syswarn( " -- zero entry ignored\n" );
return;
}
}
else
timenow = wp->w_finishtime;
if ( !flg.i || wp->w_uid == individual )
(*f)( wp );
}
/*
* init initialise all times
* ====
*/
init( dp )
register struct dtmp *dp;
{
# ifdef TIME_TRACE
print_times( "init", TT_ALL );
# endif TIME_TRACE
#ifdef DEBUG
if ( flg.y )
syswarn( "init at %s", ctime( dp->d_newtime ) );
#endif
do
year =+ YEAR;
while
( year <= dp->d_newtime );
midnight = year - YEAR;
fixuptime( dp );
lastprint = midnight - DAY;
sys.st_boottime = lastprint;
flg.z++;
#ifdef DEBUG
if ( flg.y )
syswarn( "init: hour is %s", ctime( hour ) );
#endif
# ifdef TIME_TRACE
print_times( "init", TT_ALL );
# endif TIME_TRACE
}
#endif AUSAM