home *** CD-ROM | disk | FTP | other *** search
- /*
- pegio.c
- */
-
- #include "peg.h"
-
- #define HEADER "User Due Back Comment"
- #define VHEADER "User Logged Off Due Back Name"
-
- /*
- Report pegboard for 1 or all users. Call with user number 0 to
- get them all.
-
- */
- report( who, nohdr )
- int who; /* User number */
- int nohdr; /* Quiet */
- {
- extern char *pegfnm;
- extern int vrbse;
-
- static char *months [] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" };
- static char *days [] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
-
- FILE *pegfd;
- char tb[BUFSIZ+1];
- char cb[BUFSIZ+1];
- long tlo;
- long tdb;
- int u;
- struct tm *j;
- struct passwd *p;
-
- if( ! nohdr )
- puts( vrbse ? VHEADER : HEADER );
- if(( pegfd = fopen( pegfnm, "r" )) == NULL ) {
- if( errno == ENOENT )
- exit( 0 );
- sprintf( tb,
- "Cannot read pegboard file \"%s\"", pegfnm );
- faterr( tb ); /* Exits. */
- }
-
- while(( fgets( tb, BUFSIZ, pegfd )) != NULL) {
- cb[0] = '\0';
- sscanf( tb, "%d %ld %ld %64[ -~\t]\n", &u, &tlo, &tdb, cb );
-
- if(( ! who ) || who == u ) {
- p = getpwuid( u );
-
- if( vrbse) {
- j = localtime( &tlo );
- printf( "%-7.8s %3s %3s %2d %2d:%02d ",
- p->pw_name,
- days[j->tm_wday], months[j->tm_mon],
- j->tm_mday, j->tm_hour, j->tm_min );
- j = localtime( &tdb );
- printf( "%3s %3s %2d %2d:%02d %02d %.24s\n",
- days[j->tm_wday], months[j->tm_mon],
- j->tm_mday, j->tm_hour, j->tm_min, j->tm_year,
- p->pw_gecos );
- if( cb[0] )
- printf(
- " %.64s\n",
- cb);
- }
- else {
- j = localtime( &tdb );
- printf( "%-24.25s %3s %3s %2d %2d:%02d %02d %.32s\n",
- p->pw_gecos,
- days[j->tm_wday], months[j->tm_mon],
- j->tm_mday, j->tm_hour, j->tm_min, j->tm_year, cb );
- }
-
- if( setpwent( ) == EOF )
- faterr( "cannot reset password file" ); /* Exits. */
- }
- endpwent( );
- }
- fclose( pegfd );
- }
-
- /*
- Update the pegboard. Dates gone by do not have the associated
- entry deleted but if x is 0 then the users entry is expunged.
- */
- upddbdf( ru, x )
- int ru; /* User number *.
- int x; /* Delete peg flag */
- {
- extern struct tm today;
- extern char *invkst;
- extern char *pegfnm;
- extern char *comment;
- extern int eod; /* Round off to the start of day found in rc */
- extern int admupd; /* Administrator updating mortals peg */
- extern int quiet; /* Supresses printing of time when done */
- extern long duback;
- extern long starts[];
-
- extern int cleanup( );
- int ( *clnp )( );
- int pegfd;
- int clfd;
- FILE *tfp;
- char tb[BUFSIZ+1];
- char cb[BUFSIZ+1];
- char tmpf[LPNMAX];
- long tu;
- long bu;
- int nu;
- long stat = 0;
-
- clnp = cleanup;
- signal( SIGHUP, clnp );
- signal( SIGQUIT, clnp );
- signal( SIGINT, clnp );
- signal( SIGILL, clnp );
- signal( SIGIOT, clnp );
- signal( SIGEMT, clnp );
- signal( SIGFPE, clnp );
- signal( SIGBUS, clnp );
- signal( SIGSEGV, clnp );
- signal( SIGSYS, clnp );
- signal( SIGTERM, clnp );
-
- umask( 022 );
- sprintf( tmpf, "%s/%s", pegdir, TMPLATE );
- mktemp( tmpf );
- if(( tfp = fopen( tmpf, "w+" )) == NULL ) {
- sprintf( tb,
- "could not open pegboard copy file \"%s\"", tmpf );
- faterr( tb ); /* Exits. */
- }
-
- umask( 0111 );
- if(( pegfd = open( pegfnm, O_RDWR )) == (-1)) {
- sprintf( tb,
- "could not open pegboard file \"%s\"", pegfnm );
- faterr( tb ); /* Exits. */
- }
-
- pblock( pegfd );
- if( ! x ) {
- /*
- If pegging out and end of day then round off the time to
- the start time for that day (as found in rc)
- */
- if( eod ) {
- int dbdy;
- int dy;
-
- stat = 0;
- /*
- Skip over any days that are not found in rc file.
- Check elements of due back times array, starting
- from the day in duback, up to a week from then
- */
- dbdy = dy = localtime( &duback )->tm_wday;
- while( starts[dbdy] == ( -1 )) {
- /*
- If wrapped around then no start times are spec'd
- */
- if( dy == ( dbdy = ( dbdy == 6 ? 0 : ++dbdy ))) {
- stat = 0;
- break;
- }
- /*
- If the day not spec'd then goto next day
- */
- stat += 86400;
- }
- /*
- Add in offset to next day with start time, if any
- Round to the day boundary and add the start itme for that
- day, if any
- */
- duback += stat;
- dround( &duback );
- duback +=
- (( stat = starts[ localtime( &duback )->tm_wday ]) == ( -1 )
- ? 0L : stat );
- }
- /*
- If admin is updating for someone else then keep the old
- logout time and comment, unless "-r" given on command line.
- */
- if( admupd ) {
- /*
- Admin update
- */
- while(( igets( tb, BUFSIZ, pegfd )) != NULL ) {
- cb[0] = '\0';
- sscanf( tb, "%d %ld %ld %64[ -~\t]", &nu, &tu, &bu, cb );
- if( ru != nu )
- continue;
- break; /* Found mortals entry */
- }
- if( lseek( pegfd, 0L, 0 ) == ( -1 )) {
- sprintf( tb, "could not rewind \"%s\"", pegfnm );
- faterr( tb ); /* Exits. */
- }
- if( ! *comment )
- strcpy( comment, cb );
- }
- /*
- If normal run then put the current time in the logout field
- */
- else
- time( &tu );
- if( duback < tu ) {
- fprintf( stderr, "%s: too late\n", invkst );
- cleanup( 1 );
- }
- /*
- If there is a discrepancy due to daylight savings time between
- now and the target date then fix it.
- */
- if( today.tm_isdst ^ localtime( &duback )->tm_isdst )
- duback = ( today.tm_isdst ? duback + 3600 : duback - 3600 );
- fprintf( tfp, "%d %ld %ld %.64s\n", ru, tu, duback,
- comment == NULL ? "" : comment );
- }
- while(( igets( tb, BUFSIZ, pegfd )) != NULL ) {
- cb[0] = '\0';
- sscanf( tb, "%d %ld %ld %64[ -~\t]", &nu, &tu, &bu, cb );
- if( ru != nu )
- fprintf( tfp, "%d %ld %ld %s\n", nu, tu, bu, cb );
- }
-
- if( fseek( tfp, (long)0, 0 )) {
- sprintf( tb, "could not rewind \"%s\"", tmpf );
- faterr( tb ); /* Exits. */
- }
- sprintf( cb,
- "cannot update pegboard \"%s\", there is a copy in \"%s\"",
- pegfnm, tmpf );
- /*
- Clobber the old pegboard
- */
- if((( clfd = open( pegfnm, O_WRONLY|O_TRUNC )) == (-1))
- || ( close( clfd )))
- faterr( cb ); /* Exits. */
- /*
- Copy tmp file back onto pegboard
- */
- if( lseek( pegfd, 0L, 0 ) == ( -1 ))
- faterr( cb );
- while( fgets( tb, BUFSIZ, tfp ) != NULL ) {
- if( write( pegfd, tb, (unsigned)strlen( tb )) == ( -1 ))
- faterr( cb ); /* Exits. */
- }
-
- pbunlock( pegfd );
-
- if( close( pegfd ))
- faterr( cb ); /* Exits. */
- /*
- Clobber tmp file, ensure pegboard available to all
- */
- if( unlink( tmpf ))
- fprintf( stderr, "%s: could not remove file \"%s\" (errno %d)\n",
- invkst, tmpf, errno );
- chmod( pegfnm, 0666 ); /* rw-rw-rw- */
-
- if(( ! quiet ) && ( ! x ))
- showtime( &duback );
- return( 0 );
- }
-
- /*
- Read a shorter than n \n terminated line from a fd
- */
- char *igets( s, n, fd )
- char *s;
- int n;
- int fd;
- {
- char *t;
-
- t = s;
- while( --n ) {
- switch( read( fd, t, 1 )) {
- case 1:
- if( *t++ == '\n' ) { /* EOL? */
- *t = '\0';
- return( s );
- }
- continue;
-
- case 0: /* EOF? */
- return( NULL );
-
- case -1:
- default:
- sprintf( s,
- "error %d reading file descriptor %d",
- errno, fd );
- faterr( s ); /* Exits. */
- }
- }
- /*
- > n bytes up to next \n in file, return what's collected so far
- */
- *t = '\0';
- return( s );
- }
-
- rcinit( )
- {
- extern char *pegfnm;
- extern char *pegdir;
- FILE *rcfp;
- char tb[BUFSIZ];
-
- /*
- SUN - SAT must use the 0 - 6 slots!
- */
- # define SUN 0
- # define MON 1
- # define TUE 2
- # define WED 3
- # define THU 4
- # define FRI 5
- # define SAT 6
- # define NOPEGTK 7
- # define PEGDIR 8
-
- static char *srctkns[] = {
- "sun", "mon", "tue", "wed", "thu", "fri", "sat",
- "nounpeg", "pegdir",
- "" };
- static char *urctkns[] = {
- "sun", "mon", "tue", "wed", "thu", "fri", "sat",
- "" };
-
- /*
- Read the system rc file, consider it mandatory
- */
- if(( rcfp = fopen( RCFNAM, "r" )) == NULL ) {
- sprintf( tb, "cannot open \"%s\"", RCFNAM );
- faterr( tb ); /* Exits. */
- }
- finit( rcfp, srctkns );
- fclose( rcfp );
-
- /*
- Read the users rc file, but ignore if it does not exist
- */
- sprintf( tb, "%s/%s", getenv( HOMENV ), PEGRCFN );
- if(( rcfp = fopen( tb, "r" )) != NULL )
- finit( rcfp, urctkns );
- fclose( rcfp );
- /*
- If we did not pick up names in the system default file
- then assign the defaults
- */
- if( pegfnm == NULL )
- pegfnm = PEGBOARD;
- if( pegdir == NULL )
- pegdir = PBDIR;
- return( 0 );
- }
-
- void finit( rcfp, tkns )
- FILE *rcfp;
- char *tkns[];
- {
- # define TSEPCH " \t=\n"
- char tb[BUFSIZ*2];
- int i;
- char *ttynm;
- char *tkargp;
- extern char *pegfnm;
- extern char *pegdir;
- extern int chk; /* Set for check runs */
- extern int normpeg;
- extern long starts[];
-
- ttynm = ttyname( 0 );
-
- while(fgets( tb, BUFSIZ, rcfp ) != NULL ) {
- tkargp = strtok( tb, TSEPCH );
- lows( tkargp );
- for( i = 0 ; *tkns[i] ; i++ ) {
- if( ! strncmp( tb, tkns[i], strlen( tkns[i] ))) {
- switch( i ) {
- /*
- Default start times
- */
- case SUN:
- case MON:
- case TUE:
- case WED:
- case THU:
- case FRI:
- case SAT:
- starts[i] = fixstrt( strtok( 0, TSEPCH ));
- continue;
- /*
- Is terminal (modem most likely) on the no peg out list?
- */
- case NOPEGTK:
- tkargp = strtok( 0, TSEPCH );
- if((( ! strcmp( ttynm, tkargp )))
- && ( ! chk ))
- normpeg++;
- continue;
- /*
- Pegboard directory? Get pegboard filename
- */
- case PEGDIR:
- tkargp = strtok( 0, TSEPCH );
- pegfnm =
- malloc((unsigned)
- strlen( tkargp ) + strlen( PBFNM ) + 2 );
- sprintf( pegfnm, "%s/%s", tkargp, PBFNM );
- continue;
-
- default:
- sprintf( tb,
- "init file \"%s\" garbled", RCFNAM );
- faterr( tb ); /* Exits. */
- } /* End of switch */
- } /* End of if */
- } /* End of for */
- } /* End of while */
- }
-
- pblock( fd )
- int fd;
- {
- extern int errno;
- struct flock lk;
-
- lk.l_type = F_WRLCK;
- lk.l_whence = 0;
- lk.l_start = 0L;
- lk.l_len = 0L;
-
- if( fcntl( fd, F_SETLK, &lk ) == (-1)) {
- char msg[BUFSIZ];
- sprintf( msg, "fcntl lock failed on pegboard, errno %d", errno );
- faterr( msg ); /* Exits. */
- }
- return( 0 );
- }
-
- pbunlock( fd )
- int fd;
- {
- extern char *invkst;
- struct flock lk;
-
- lk.l_type = F_UNLCK;
- lk.l_whence = 0;
- lk.l_start = 0L;
- lk.l_len = 0L;
-
- if( fcntl( fd, F_SETLK, &lk ) == (-1))
- fprintf( stderr, "%s: fcntl unlock failed on pegboard", invkst );
- return( 0 );
- }
-
- long fixstrt( s )
- char *s;
- {
- int h;
- int m;
-
- if( ! isdigit( *s ))
- return( -1L );
- sscanf( s, "%d:%d", &h, &m );
-
- return((long)(( h * 3600 ) + ( m * 60 )));
- }
-
- chkpeg( u )
- unsigned short u;
- {
- FILE *pegfd;
- char b[30];
- int v;
-
- if(( pegfd = fopen( pegfnm, "r" )) == NULL )
- return( -1 );
-
- while( fgets( b, 30, pegfd ) != NULL ) {
- sscanf( b, "%d", &v );
- if( v == u ) {
- if( close( pegfd ))
- faterr( "system error closing pegboard" );
- return( 0 );
- }
- }
- if( close( pegfd ))
- faterr( "system error closing pegboard" );
- return( 1 );
- }
-
- void faterr( m )
- char *m;
- {
- extern char *invkst;
-
- fprintf( stderr, "%s: %s\n", invkst, m );
- perror( "last system error" );
- cleanup( errno );
- }
-
- cleanup( s )
- int s;
- {
- exit( s );
- }
-