home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / pegboard / pegio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-26  |  10.6 KB  |  519 lines

  1. /*
  2.     pegio.c
  3. */
  4.  
  5. #include "peg.h"
  6.  
  7. #define HEADER "User                     Due Back              Comment"
  8. #define VHEADER "User    Logged Off        Due Back             Name"
  9.  
  10. /*
  11.     Report pegboard for 1 or all users. Call with user number 0 to
  12.     get them all.
  13.  
  14. */
  15. report( who, nohdr )
  16. int who;    /* User number    */
  17. int nohdr;    /* Quiet    */
  18. {
  19.     extern char *pegfnm;
  20.     extern int    vrbse;
  21.  
  22.     static    char *months [] =    {
  23.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  24.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""    };
  25.     static    char *days [] =    {
  26.         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"    };
  27.  
  28.     FILE    *pegfd;
  29.     char    tb[BUFSIZ+1];
  30.     char    cb[BUFSIZ+1];
  31.     long    tlo;
  32.     long    tdb;
  33.     int    u;
  34.     struct tm    *j;
  35.     struct passwd *p;
  36.  
  37.     if( ! nohdr )
  38.             puts( vrbse ? VHEADER : HEADER );
  39.     if(( pegfd = fopen( pegfnm, "r" )) == NULL )    {
  40.         if( errno == ENOENT )
  41.             exit( 0 );
  42.         sprintf( tb,
  43.         "Cannot read pegboard file \"%s\"", pegfnm );
  44.         faterr( tb );    /* Exits.    */
  45.     }
  46.  
  47.     while(( fgets( tb, BUFSIZ, pegfd )) != NULL)    {
  48.         cb[0] = '\0';
  49.         sscanf( tb, "%d %ld %ld %64[ -~\t]\n", &u, &tlo, &tdb, cb );
  50.  
  51.         if(( ! who ) || who == u )    {
  52.             p = getpwuid( u );
  53.  
  54.             if( vrbse)    {
  55.                 j = localtime( &tlo );
  56.                 printf( "%-7.8s %3s %3s %2d %2d:%02d  ",
  57.                 p->pw_name,
  58.                 days[j->tm_wday], months[j->tm_mon],
  59.                 j->tm_mday, j->tm_hour, j->tm_min );
  60.                 j = localtime( &tdb );
  61.                 printf( "%3s %3s %2d %2d:%02d %02d  %.24s\n",
  62.                 days[j->tm_wday], months[j->tm_mon],
  63.                 j->tm_mday, j->tm_hour, j->tm_min, j->tm_year,
  64.                 p->pw_gecos );
  65.                 if( cb[0] )
  66.                     printf(
  67.                     "        %.64s\n",
  68.                     cb);
  69.             }
  70.             else    {
  71.                 j = localtime( &tdb );
  72.                 printf( "%-24.25s %3s %3s %2d %2d:%02d %02d   %.32s\n",
  73.                 p->pw_gecos,
  74.                 days[j->tm_wday], months[j->tm_mon],
  75.                 j->tm_mday, j->tm_hour, j->tm_min, j->tm_year, cb );
  76.             }
  77.  
  78.             if( setpwent( ) == EOF )
  79.                 faterr( "cannot reset password file" );    /* Exits.    */
  80.         }
  81.         endpwent( );
  82.     }
  83.     fclose( pegfd );
  84. }
  85.  
  86. /*
  87.     Update the pegboard.  Dates gone by do not have the associated
  88.     entry deleted but if x is 0 then the users entry is expunged.
  89. */
  90. upddbdf( ru, x )
  91. int ru;    /* User number    *.
  92. int x;    /* Delete peg flag    */
  93. {
  94.     extern struct    tm today;
  95.     extern char    *invkst;
  96.     extern char *pegfnm;
  97.     extern char *comment;
  98.     extern int    eod;    /* Round off to the start of day found in rc    */
  99.     extern int    admupd;    /* Administrator updating mortals peg    */
  100.     extern int    quiet;    /* Supresses printing of time when done    */
  101.     extern long    duback;
  102.     extern long starts[];
  103.  
  104.     extern int    cleanup( );
  105.     int    ( *clnp )( );
  106.     int    pegfd;
  107.     int    clfd;
  108.     FILE    *tfp;
  109.     char    tb[BUFSIZ+1];
  110.     char    cb[BUFSIZ+1];
  111.     char    tmpf[LPNMAX];
  112.     long    tu;
  113.     long    bu;
  114.     int    nu;
  115.     long    stat = 0;
  116.  
  117.     clnp = cleanup;
  118.     signal( SIGHUP, clnp );
  119.     signal( SIGQUIT, clnp );
  120.     signal( SIGINT, clnp );
  121.     signal( SIGILL, clnp );
  122.     signal( SIGIOT, clnp );
  123.     signal( SIGEMT, clnp );
  124.     signal( SIGFPE, clnp );
  125.     signal( SIGBUS, clnp );
  126.     signal( SIGSEGV, clnp );
  127.     signal( SIGSYS,    clnp );
  128.     signal( SIGTERM, clnp );
  129.  
  130.     umask( 022 );
  131.     sprintf( tmpf, "%s/%s", pegdir, TMPLATE );
  132.     mktemp( tmpf );
  133.     if(( tfp = fopen( tmpf, "w+" )) == NULL )    {
  134.         sprintf( tb,
  135.         "could not open pegboard copy file \"%s\"", tmpf );
  136.         faterr( tb );    /* Exits.    */
  137.     }
  138.  
  139.     umask( 0111 );
  140.     if(( pegfd = open( pegfnm, O_RDWR )) == (-1))    {
  141.         sprintf( tb,
  142.         "could not open pegboard file \"%s\"", pegfnm );
  143.         faterr( tb );    /* Exits.    */
  144.     }
  145.  
  146.     pblock( pegfd );
  147.     if( ! x )    {
  148.         /*
  149.             If pegging out and end of day then round off the time to
  150.             the start time for that day (as found in rc)
  151.         */
  152.         if( eod )    {
  153.             int dbdy;
  154.             int dy;
  155.  
  156.             stat = 0;
  157.             /*
  158.                 Skip over any days that are not found in rc file.
  159.                 Check elements of due back times array, starting
  160.                 from the day in duback, up to a week from then
  161.             */
  162.             dbdy = dy = localtime( &duback )->tm_wday;
  163.             while( starts[dbdy] == ( -1 ))    {
  164.                 /*
  165.                     If wrapped around then no start times are spec'd
  166.                 */
  167.                 if( dy == ( dbdy = ( dbdy == 6 ? 0 : ++dbdy )))    {
  168.                     stat = 0;
  169.                     break;
  170.                 }
  171.                 /*
  172.                     If the day not spec'd then goto next day
  173.                 */
  174.                 stat += 86400;
  175.             }
  176.             /*
  177.                 Add in offset to next day with start time, if any
  178.                 Round to the day boundary and add the start itme for that
  179.                 day, if any
  180.             */
  181.             duback += stat;
  182.             dround( &duback );
  183.             duback +=
  184.             (( stat = starts[ localtime( &duback )->tm_wday ]) == ( -1 )
  185.             ? 0L : stat );
  186.         }
  187.         /*
  188.             If admin is updating for someone else then keep the old
  189.             logout time and comment, unless "-r" given on command line.
  190.         */
  191.         if( admupd )    {
  192.             /*
  193.                 Admin update
  194.             */
  195.             while(( igets( tb, BUFSIZ, pegfd )) != NULL )    {
  196.                 cb[0] = '\0';
  197.                 sscanf( tb, "%d %ld %ld %64[ -~\t]", &nu, &tu, &bu, cb );
  198.                 if( ru != nu )
  199.                     continue;
  200.                 break;    /* Found mortals entry    */
  201.             }
  202.             if( lseek( pegfd, 0L, 0 ) == ( -1 ))    {
  203.                 sprintf( tb, "could not rewind \"%s\"", pegfnm );
  204.                 faterr( tb );    /* Exits.    */
  205.             }
  206.             if( ! *comment )
  207.                 strcpy( comment, cb );
  208.         }
  209.         /*
  210.             If normal run then put the current time in the logout field
  211.         */
  212.         else
  213.             time( &tu );
  214.         if( duback < tu )    {
  215.             fprintf( stderr, "%s: too late\n", invkst );
  216.             cleanup( 1 );
  217.         }
  218.         /*
  219.             If there is a discrepancy due to daylight savings time between
  220.             now and the target date then fix it.
  221.         */
  222.         if( today.tm_isdst ^ localtime( &duback )->tm_isdst )
  223.             duback = ( today.tm_isdst ? duback + 3600 : duback - 3600 );
  224.         fprintf( tfp, "%d %ld %ld %.64s\n", ru, tu, duback,
  225.         comment == NULL ? "" : comment );
  226.     }
  227.     while(( igets( tb, BUFSIZ, pegfd )) != NULL )    {
  228.         cb[0] = '\0';
  229.         sscanf( tb, "%d %ld %ld %64[ -~\t]", &nu, &tu, &bu, cb );
  230.         if( ru != nu )
  231.             fprintf( tfp, "%d %ld %ld %s\n", nu, tu, bu, cb );
  232.     }
  233.  
  234.     if( fseek( tfp, (long)0, 0 ))    {
  235.         sprintf( tb, "could not rewind \"%s\"", tmpf );
  236.         faterr( tb );    /* Exits.    */
  237.     }
  238.     sprintf( cb,
  239.     "cannot update pegboard \"%s\", there is a copy in \"%s\"",
  240.     pegfnm, tmpf );
  241.     /*
  242.         Clobber the old pegboard
  243.     */
  244.     if((( clfd = open( pegfnm, O_WRONLY|O_TRUNC )) == (-1))    
  245.     || ( close( clfd )))
  246.         faterr( cb );    /* Exits.    */
  247.     /*
  248.         Copy tmp file back onto pegboard
  249.     */
  250.     if( lseek( pegfd, 0L, 0 ) == ( -1 ))
  251.         faterr( cb );
  252.     while( fgets( tb, BUFSIZ, tfp ) != NULL )    {
  253.         if( write( pegfd, tb, (unsigned)strlen( tb )) == ( -1 ))
  254.             faterr( cb );    /* Exits.    */
  255.     }
  256.  
  257.     pbunlock( pegfd );
  258.  
  259.     if( close( pegfd ))
  260.         faterr( cb );    /* Exits.    */
  261.     /*
  262.         Clobber tmp file, ensure pegboard available to all
  263.     */
  264.     if( unlink( tmpf ))
  265.         fprintf( stderr, "%s: could not remove file \"%s\" (errno %d)\n",
  266.         invkst, tmpf, errno );
  267.     chmod( pegfnm, 0666 );    /* rw-rw-rw-    */
  268.  
  269.     if(( ! quiet ) && ( ! x ))
  270.         showtime( &duback );
  271.     return( 0 );
  272. }
  273.  
  274. /*
  275.     Read a shorter than n \n terminated line from a fd
  276. */
  277. char *igets( s, n, fd )
  278. char *s;
  279. int n;
  280. int fd;
  281. {
  282.     char *t;
  283.  
  284.     t = s;
  285.     while( --n )    {
  286.         switch( read( fd, t, 1 ))    {
  287.             case 1:
  288.                 if( *t++ == '\n' )    {    /* EOL?    */
  289.                     *t = '\0';
  290.                     return( s );
  291.                 }
  292.                 continue;
  293.  
  294.             case 0:    /* EOF?    */
  295.                 return( NULL );
  296.  
  297.             case -1:
  298.             default:
  299.                 sprintf( s,
  300.                 "error %d reading file descriptor %d",
  301.                 errno, fd );
  302.                 faterr( s );    /* Exits.    */
  303.         }
  304.     }
  305.     /*
  306.         > n bytes up to next \n in file, return what's collected so far
  307.     */
  308.     *t = '\0';
  309.     return( s );
  310. }
  311.  
  312. rcinit( )
  313. {
  314.     extern char *pegfnm;
  315.     extern char *pegdir;
  316.     FILE *rcfp;
  317.     char tb[BUFSIZ];
  318.  
  319.     /*
  320.         SUN - SAT must use the 0 - 6 slots!
  321.     */
  322. #    define SUN    0
  323. #    define MON    1
  324. #    define TUE    2
  325. #    define WED    3
  326. #    define THU    4
  327. #    define FRI    5
  328. #    define SAT    6
  329. #    define NOPEGTK    7
  330. #    define PEGDIR    8
  331.  
  332.     static char *srctkns[] =    {
  333.         "sun", "mon", "tue", "wed", "thu", "fri", "sat",
  334.          "nounpeg", "pegdir",
  335.          "" };
  336.     static char *urctkns[] =    {
  337.         "sun", "mon", "tue", "wed", "thu", "fri", "sat",
  338.          "" };
  339.  
  340.     /*
  341.         Read the system rc file, consider it mandatory
  342.     */
  343.     if(( rcfp = fopen( RCFNAM, "r" )) == NULL )    {
  344.         sprintf( tb, "cannot open \"%s\"", RCFNAM );
  345.         faterr( tb );    /* Exits.    */
  346.     }
  347.     finit( rcfp, srctkns );
  348.     fclose( rcfp );
  349.  
  350.     /*
  351.         Read the users rc file, but ignore if it does not exist
  352.     */
  353.     sprintf( tb, "%s/%s", getenv( HOMENV ), PEGRCFN );
  354.     if(( rcfp = fopen( tb, "r" )) != NULL )
  355.         finit( rcfp, urctkns );
  356.     fclose( rcfp );
  357.     /*
  358.         If we did not pick up names in the system default file
  359.         then assign the defaults
  360.     */
  361.     if( pegfnm == NULL )
  362.         pegfnm = PEGBOARD;
  363.     if( pegdir == NULL )
  364.         pegdir = PBDIR;
  365.     return( 0 );
  366. }
  367.  
  368. void finit( rcfp, tkns )
  369. FILE *rcfp;
  370. char *tkns[];
  371. {
  372. #    define TSEPCH    " \t=\n"
  373.     char tb[BUFSIZ*2];
  374.     int i;
  375.     char *ttynm;
  376.     char *tkargp;
  377.     extern char *pegfnm;
  378.     extern char *pegdir;
  379.     extern int chk;    /* Set for check runs    */
  380.     extern int    normpeg;
  381.     extern long starts[];
  382.  
  383.     ttynm = ttyname( 0 );
  384.  
  385.     while(fgets( tb, BUFSIZ, rcfp ) != NULL )    {
  386.         tkargp = strtok( tb, TSEPCH );
  387.         lows( tkargp );
  388.         for( i = 0 ; *tkns[i] ; i++ )    {
  389.             if( ! strncmp( tb, tkns[i], strlen( tkns[i] )))    {
  390.                 switch( i )    {
  391.                     /*
  392.                         Default start times
  393.                     */
  394.                     case SUN:
  395.                     case MON:
  396.                     case TUE:
  397.                     case WED:
  398.                     case THU:
  399.                     case FRI:
  400.                     case SAT:
  401.                         starts[i] = fixstrt( strtok( 0, TSEPCH ));
  402.                         continue;
  403.                     /*
  404.                         Is terminal (modem most likely) on the no peg out list?
  405.                     */
  406.                     case NOPEGTK:
  407.                         tkargp = strtok( 0, TSEPCH );
  408.                         if((( ! strcmp( ttynm, tkargp )))
  409.                         && ( ! chk ))
  410.                             normpeg++;
  411.                         continue;
  412.                     /*
  413.                         Pegboard directory? Get pegboard filename
  414.                     */
  415.                     case PEGDIR:
  416.                         tkargp = strtok( 0, TSEPCH );
  417.                         pegfnm =
  418.                         malloc((unsigned)
  419.                         strlen( tkargp ) + strlen( PBFNM ) + 2 );
  420.                         sprintf( pegfnm, "%s/%s", tkargp, PBFNM );
  421.                         continue;
  422.  
  423.                     default:
  424.                         sprintf( tb,
  425.                         "init file \"%s\" garbled", RCFNAM );
  426.                         faterr( tb );    /* Exits.    */
  427.                 }    /* End of switch    */
  428.             }    /* End of if    */
  429.         }    /* End of for    */
  430.     }    /* End of while    */
  431. }
  432.  
  433. pblock( fd )
  434. int fd;
  435. {
  436.     extern int errno;
  437.     struct flock lk;
  438.  
  439.     lk.l_type = F_WRLCK;
  440.     lk.l_whence = 0;
  441.     lk.l_start = 0L;
  442.     lk.l_len = 0L;
  443.  
  444.     if( fcntl( fd, F_SETLK, &lk ) == (-1))    {
  445.         char msg[BUFSIZ];
  446.         sprintf( msg, "fcntl lock failed on pegboard, errno %d", errno );
  447.         faterr( msg );    /* Exits.    */
  448.     }
  449.     return( 0 );
  450. }
  451.  
  452. pbunlock( fd )
  453. int fd;
  454. {
  455.     extern char *invkst;
  456.     struct flock lk;
  457.  
  458.     lk.l_type = F_UNLCK;
  459.     lk.l_whence = 0;
  460.     lk.l_start = 0L;
  461.     lk.l_len = 0L;
  462.  
  463.     if( fcntl( fd, F_SETLK, &lk ) == (-1))
  464.         fprintf( stderr, "%s: fcntl unlock failed on pegboard", invkst );
  465.     return( 0 );
  466. }
  467.  
  468. long fixstrt( s )
  469. char *s;
  470. {
  471.     int h;
  472.     int m;
  473.  
  474.     if( ! isdigit( *s ))
  475.         return( -1L );
  476.     sscanf( s, "%d:%d", &h, &m );
  477.  
  478.     return((long)(( h * 3600 ) + ( m * 60 )));
  479. }
  480.  
  481. chkpeg( u )
  482. unsigned short u;
  483. {
  484.     FILE *pegfd;
  485.     char b[30];
  486.     int v;
  487.  
  488.     if(( pegfd = fopen( pegfnm, "r" )) == NULL )
  489.         return( -1 );
  490.  
  491.     while( fgets( b, 30, pegfd ) != NULL )    {
  492.         sscanf( b, "%d", &v );
  493.         if( v == u )    {
  494.             if( close( pegfd ))
  495.                 faterr( "system error closing pegboard" );
  496.             return( 0 );
  497.         }
  498.     }
  499.     if( close( pegfd ))
  500.         faterr( "system error closing pegboard" );
  501.     return( 1 );
  502. }
  503.  
  504. void faterr( m )
  505. char *m;
  506. {
  507.     extern char *invkst;
  508.  
  509.     fprintf( stderr, "%s: %s\n", invkst, m );
  510.     perror( "last system error" );
  511.     cleanup( errno );
  512. }
  513.  
  514. cleanup( s )
  515. int s;
  516. {
  517.     exit( s );
  518. }
  519.