home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / finger / part04 / conf.c next >
Encoding:
C/C++ Source or Header  |  1992-04-03  |  8.8 KB  |  441 lines

  1. /*
  2.  * conf.c -- read run time configuration file for finger
  3.  *
  4.  * Copyright (C) 1990  Philip L. Budne
  5.  *
  6.  * This file is part of "Phil's Finger Program".
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 1, or (at your option)
  11.  * any later version.
  12.  *
  13.  */
  14.  
  15. /* TODO:
  16.  * implement options and route
  17.  * do ttylocs from here? (nah, hardle needs them)
  18.  */
  19.  
  20. /*
  21.  * The idea for formatting phone numbers comes from
  22.  * Michael Thompson <thompson@dalcs.UUCP> Dalhousie University,
  23.  * Halifax, NS in comp.bugs.4bsd on Sept 25, 1987 
  24.  * "BSD4.3 finger is Berkley dependent. +FIX" 
  25.  */
  26.  
  27. # ifndef lint
  28. static char *rcsid = "$Id: conf.c,v 3.0 90/07/06 13:10:27 budd Rel $";
  29. # endif /* lint not defined */
  30.  
  31. # include <stdio.h>
  32. # include <strings.h>
  33. # include <ctype.h>
  34. # include <pwd.h>
  35. # include <grp.h>
  36. # include "person.h"
  37. # include "finger.h"
  38. # include "args.h"            /* sw_debug */
  39.  
  40. # define CONF "finger.conf"
  41. # define NUMBER '#'
  42. # define COMMENT '!'
  43.  
  44. LOCAL int initialized = FALSE;
  45. LOCAL char *confdirs[] = {
  46. # ifdef CONFDIRS
  47.     CONFDIRS,
  48. # endif /* CONFDIRS defined */
  49.     "/etc",
  50.     "/usr/local/etc",
  51.     "/usr/etc",
  52.     ".",                /* for debugging.. move to first? */
  53.     NULL
  54. };
  55.  
  56. # define NBUILDINGS 10            /* UGH! */
  57. LOCAL struct building {
  58.     char code;
  59.     char *name;
  60. } buildings[NBUILDINGS];
  61. LOCAL int nbuildings = 0;
  62.  
  63. # define NACCTS 32            /* UGH! */
  64. LOCAL struct acct {
  65.     unsigned short min, max;
  66.     char group, *name;
  67. } accts[NACCTS];
  68. LOCAL int naccts = 0;
  69.  
  70. # define NPHONES 32            /* UGH! */
  71. LOCAL struct phone {
  72.     int splats;
  73.     char *pat;
  74. } phones[NPHONES];
  75. LOCAL int nphones = 0;
  76.  
  77. # define NHIDDEN 32            /* UGH! */
  78. char *hidden[NHIDDEN];
  79. LOCAL int nhidden = 0;
  80.  
  81. # define NPREFIX 32            /* UGH! */
  82. char *prefix[NPREFIX];
  83. LOCAL int nprefixes = 0;
  84.  
  85. GLOBAL BOOL
  86. read_conf() {
  87.     FILE *f;
  88.     char **dp;
  89.     char buf[ 512 ];
  90.     enum { START, ACCT, BUILDING, HIDDEN, OPT, PHONE, PREFIX, ROUTE } state;
  91.  
  92.     if( initialized )
  93.     return( TRUE );
  94.     initialized = TRUE;
  95.  
  96.     /* read env variable for path(s)? */
  97.  
  98.     for( dp = confdirs, f = NULL; f == NULL && *dp != NULL; dp++ ) {
  99.     sprintf( buf, "%s/%s", *dp, CONF );
  100.     f = fopen( buf, "r" );
  101.     }
  102.     if( f == NULL )
  103.     return( FALSE );
  104.  
  105.     if( sw_debug )
  106.     printf("%s:\n", buf );
  107.  
  108.     state = START;
  109.     if( fgets( buf, sizeof( buf ), f ) == NULL ) {
  110.     fclose( f );
  111.     return( FALSE );
  112.     }
  113.  
  114.     do {                /* ...while fgets */
  115.     char *cp;
  116.  
  117.     switch( buf[0] ) {
  118.     case '%':
  119.         /* use perfect hashing? */
  120. # define PAIR(a,b) (a)<<7|(b)
  121.         switch( PAIR(buf[1],buf[2]) ) {
  122.         case PAIR('a','c'):
  123.         state = ACCT;
  124.         break;
  125.         case PAIR('b','u'):
  126.         state = BUILDING;
  127.         break;
  128.         case PAIR('h','i'):
  129.         state = HIDDEN;
  130.         break;
  131.         case PAIR('o','p'):
  132.         state = OPT;
  133.         break;
  134.         case PAIR('p','h'):
  135.         state = PHONE;
  136.         break;
  137.         case PAIR('p','r'):
  138.         state = PREFIX;
  139.         break;
  140.         case PAIR('r','o'):
  141.         state = ROUTE;
  142.         break;
  143.         default:
  144.         state = START;
  145.         break;
  146.         }
  147.         /* fall */
  148.     case COMMENT:
  149.         /* # is used in phones */
  150.         continue;
  151.     } /* switch on buf[0] */
  152.  
  153.     cp = index( buf, '\n' );
  154.     if( cp != NULL )
  155.         *cp = EOS;
  156.  
  157.     switch( state ) {
  158.     case START:
  159.         break;
  160.  
  161.     case ACCT:
  162.         if( naccts < NACCTS ) {
  163.         char temp[ 128 ], *tp;    /* FIXME */
  164.         BOOL lit, name, hyp;
  165.         int min, max, grp;
  166.         struct passwd *pw;
  167.         struct group *gr;
  168.  
  169.         name = FALSE;        /* no letters */
  170.         lit = FALSE;        /* no litteral next */
  171.         tp = temp;        /* output buffer */
  172.         for( cp = buf; *cp; cp++ ) {
  173.             if( *cp == '\\' ) {
  174.             lit = name = TRUE; /* quote next, interpret as name */
  175.             continue;
  176.             }
  177.             if( isspace(*cp) && !lit )
  178.             break;
  179.             if( !isdigit(*cp) )
  180.             name = TRUE;
  181.             *tp++ = *cp;
  182.             lit = FALSE;
  183.         }
  184.         *tp = EOS;        /* tie off string */
  185.         if( tp == temp || *cp == EOS ) /* empty string, or EOS? */
  186.             break;        /* must have two fields */
  187.  
  188.         hyp = (*cp == '-');    /* unquoted hypen means a range */
  189.         if( !name )
  190.             min = atoi( temp );
  191.         else if( (gr = getgrnam( temp )) != NULL )
  192.             min = gr->gr_gid;
  193.         else if( (pw = getpwnam( temp )) != NULL )
  194.             min = pw->pw_uid;
  195.         else
  196.             break;
  197.  
  198.         if( hyp ) {
  199.             tp = temp;
  200.             name = lit = FALSE;
  201.             for( ; *cp ; cp++ ) {
  202.             if( *cp == '\\' ) {
  203.                 /* quote next, interpret as name */
  204.                 lit = name = TRUE;
  205.                 continue;
  206.             }
  207.             if( isspace(*cp) && !lit )
  208.                 break;
  209.             if( !isdigit(*cp) )
  210.                 name = TRUE;
  211.  
  212.             *tp++ = *cp;
  213.             lit = FALSE;
  214.             }
  215.             if( tp == temp || *cp == EOS )
  216.             break;
  217.             *tp = EOS;
  218.             if( !name )
  219.             max = atoi( temp );
  220.             else if( (gr = getgrnam( temp )) != NULL )
  221.             max = gr->gr_gid;
  222.             else if( (pw = getpwnam( temp )) != NULL )
  223.             max = pw->pw_uid;
  224.             else
  225.             break;
  226.         }
  227.         else
  228.             max = min;
  229.  
  230.         if( !skipwhite(&cp) )
  231.             break;
  232.         grp = *cp++;
  233.         skipwhite(&cp);
  234.  
  235.         accts[naccts].min = min;
  236.         accts[naccts].max = max;
  237.         accts[naccts].group = grp;
  238.         accts[naccts].name = savestr( cp );
  239.         naccts++;
  240.         if( sw_debug )
  241.             printf("acct: %d-%d %c %s\n", min, max, grp, cp );
  242.         }
  243.         break;
  244.  
  245.     case BUILDING:
  246.         if( nbuildings < NBUILDINGS ) {
  247.         cp = buf+1;
  248.         if( skipwhite(&cp) ) {
  249.             buildings[nbuildings].code = buf[0];
  250.             buildings[nbuildings].name = savestr( cp );
  251.             nbuildings++;
  252.             if( sw_debug )
  253.             printf("bldg: %c %s\n", buf[0], cp );
  254.         }
  255.         }
  256.         break;
  257.  
  258.     case OPT:
  259.         /* options to set; ie; sw_berkeley, sw_its */
  260.         break;
  261.  
  262.     case PHONE:
  263.         if( nphones < NPHONES ) {
  264.         int splats;
  265.  
  266.         splats = 0;
  267.         for( cp = buf; *cp; cp++ )
  268.             if( *cp == NUMBER )
  269.             splats++;
  270.         if( splats > 0 ) {
  271.             phones[nphones].splats = splats;
  272.             phones[nphones].pat = savestr( buf );
  273.             nphones++;
  274.             if( sw_debug )
  275.             printf("phone: %d %s\n", splats, buf );
  276.         }
  277.         }
  278.         break;
  279.  
  280.     case HIDDEN:
  281.         if( nhidden < NHIDDEN ) {
  282.         hidden[nhidden] = savestr( buf );
  283.         nhidden++;
  284.         if( sw_debug )
  285.             printf("hidden: %s\n", buf );
  286.         }
  287.         break;
  288.  
  289.     case PREFIX:
  290.         if( nprefixes < NPREFIX ) {
  291.         prefix[nprefixes] = savestr( buf );
  292.         nprefixes++;
  293.         if( sw_debug )
  294.             printf("prefix: %s\n", buf );
  295.         }
  296.         break;
  297.  
  298.     case ROUTE:
  299.         break;
  300.  
  301.     } /* state switch */
  302.     } while( fgets( buf, sizeof( buf ), f ) != NULL );
  303.     if( sw_debug )
  304.     printf("\
  305. conf: %d accts, %d buildings, %d hidden, %d phones, %d prefixes\n",
  306.            naccts, nbuildings, nhidden, nphones, nprefixes );
  307.     return( TRUE );
  308. } /* read_conf */
  309.  
  310. /*
  311.  *    routines called from outside...
  312.  */
  313.  
  314. GLOBAL int ishidden( str )
  315.     char *str;
  316. {
  317.     register int i;
  318.  
  319.     for( i = 0; i < nhidden; i++ )
  320.     if( strcmp( str, hidden[i] ) == 0 )
  321.         return( TRUE );
  322.     return( FALSE );
  323. }
  324.  
  325. GLOBAL char *conf_prefix( i )
  326.     int i;
  327. {
  328.     if( i > nprefixes )
  329.     return( NULL );
  330.     return( prefix[i] );
  331. }
  332.  
  333. GLOBAL void acct_group( pp )
  334.     PERSON *pp;
  335. {
  336.     int i;
  337.     register struct acct *ap;
  338.  
  339.     for( i = 0, ap = accts; i < naccts; i++, ap++ ) {
  340.     if( ap->min <= ap->max ) {
  341.         if( pp->p_gid >= ap->min && pp->p_gid <= ap->max ) {
  342.         pp->p_group = ap->group;
  343.         return;
  344.         }
  345.     }
  346.     else if( pp->p_gid >= ap->max && pp->p_gid <= ap->min ) {
  347.         pp->p_group = ap->group;
  348.         return;
  349.     }
  350.     }
  351.     if( pp->p_gid == pp->p_uid )
  352.     pp->p_group = '.';        /* use '=' ? */
  353.     else
  354.     pp->p_group = ' ';
  355. }
  356.  
  357. GLOBAL char *acct_name( pp )
  358.     PERSON *pp;
  359. {
  360.     int i;
  361.     register struct acct *ap;
  362.  
  363.     for( i = 0, ap = accts; i < naccts; i++, ap++ ) {
  364.     if( ap->min <= ap->max ) {
  365.         if( pp->p_gid >= ap->min && pp->p_gid <= ap->max )
  366.         return( ap->name );
  367.     }
  368.     else if( pp->p_gid >= ap->max && pp->p_gid <= ap->min )
  369.         return( ap->name );
  370.     }
  371.     return( NULL );
  372. }
  373.  
  374. GLOBAL void catphone( dest, phone )
  375.     register char *dest, *phone;
  376. {
  377.     char *ph;
  378.     int digits, other, i;
  379.  
  380.     ph = phone;
  381.     for( digits = other = 0; *phone != EOS; phone++ )
  382.     if( isdigit(*phone) )
  383.         digits++;
  384.     else
  385.         other++;
  386.  
  387.     if( 
  388. # ifdef FORMAT_DIGITS_ONLY
  389.        other == 0 &&
  390. # endif /* FORMAT_DIGITS_ONLY defined */
  391.        digits > 0 ) {
  392.     while( *dest != EOS )
  393.         dest++;
  394.  
  395.     for( i = 0; i < nphones; i++ )
  396.         if( phones[i].splats == digits ) {
  397.         register char *pat;
  398.  
  399.         phone = ph;
  400.         for( pat = phones[i].pat; *pat != EOS; pat++ ) {
  401.             if( *pat == NUMBER ) {
  402.             while( !isdigit(*phone) )
  403.                 phone++;
  404.             *dest++ = *phone++;
  405.             }
  406.             else
  407.             *dest++ = *pat;
  408.         }
  409.         *dest = EOS;
  410.         return;
  411.         }
  412.     } /* other == 0 && digits > 0 */
  413.     strcat( dest, phone );
  414. }
  415.  
  416. /* given an office string, return formatted in a static buffer */
  417. # define OFFSIZ 100
  418.  
  419. GLOBAL char *office( s )
  420.     char *s;
  421. {
  422.     char offbuff[OFFSIZ];
  423.     int i, l;
  424.  
  425.     l = strlen( s );
  426.     if( l > OFFSIZ - 10 )    /* close? */
  427.     return( s );        /* good-bye */
  428.  
  429.     for( i = 0; i < nbuildings; i++ )
  430.     if( buildings[i].code == s[l-1] )
  431.         break;
  432.  
  433.     if( i >= nbuildings )
  434.     return( s );
  435.  
  436.     strcpy(offbuff, s);
  437.     offbuff[l-1] = EOS;
  438.     strcat(offbuff, buildings[i].name );
  439.     return( offbuff );
  440. } /* office */
  441.