home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.unix
- From: panos@cs.colorado.edu (Panos Tsirigotis)
- Subject: v26i268: xinetd-2.1.1 - inetd replacement with access control and logging, Part24/31
- Sender: unix-sources-moderator@gw.home.vix.com
- Approved: vixie@gw.home.vix.com
-
- Submitted-By: panos@cs.colorado.edu (Panos Tsirigotis)
- Posting-Number: Volume 26, Issue 268
- Archive-Name: xinetd-2.1.1/part24
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 24 (of 31)."
- # Contents: xinetd/parse.c
- # Wrapped by panos@mystique on Mon Jun 21 14:51:27 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'xinetd/parse.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xinetd/parse.c'\"
- else
- echo shar: Extracting \"'xinetd/parse.c'\" \(14596 characters\)
- sed "s/^X//" >'xinetd/parse.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1992 by Panagiotis Tsirigotis
- X * All rights reserved. The file named COPYRIGHT specifies the terms
- X * and conditions for redistribution.
- X */
- X
- Xstatic char RCSid[] = "$Id" ;
- X
- X#include <sys/types.h>
- X#include <netdb.h>
- X#include <string.h>
- X#include <syslog.h>
- X#include <memory.h>
- X
- X#include "misc.h"
- X#include "str.h"
- X#include "pset.h"
- X#include "sio.h"
- X
- X#include "defs.h"
- X#include "sconf.h"
- X#include "conf.h"
- X#include "attr.h"
- X#include "parse.h"
- X#include "addr.h"
- X
- Xchar *malloc() ;
- Xvoid endprotoent() ;
- Xvoid endpwent() ;
- Xvoid endgrent() ;
- Xint endnetent() ;
- Xvoid endhostent() ;
- X
- X
- Xvoid parsemsg() ;
- Xvoid msg() ;
- Xvoid out_of_memory() ;
- X
- Xchar *next_line() ;
- Xint line_has_only_1_char() ;
- Xvoid skip_entry() ;
- X
- X/*
- X * Parser functions
- X */
- Xstatus_e service_parser() ;
- Xstatus_e socket_type_parser() ;
- Xstatus_e protocol_parser() ;
- Xstatus_e wait_parser() ;
- Xstatus_e user_parser() ;
- Xstatus_e group_parser() ;
- Xstatus_e server_parser() ;
- Xstatus_e server_args_parser() ;
- Xstatus_e instances_parser() ;
- Xstatus_e log_on_success_parser() ;
- Xstatus_e log_on_failure_parser() ;
- Xstatus_e log_type_parser() ;
- Xstatus_e only_from_parser() ;
- Xstatus_e no_access_parser() ;
- Xstatus_e access_times_parser() ;
- Xstatus_e type_parser() ;
- Xstatus_e id_parser() ;
- Xstatus_e env_parser() ;
- Xstatus_e port_parser() ;
- Xstatus_e rpc_version_parser() ;
- Xstatus_e passenv_parser() ;
- Xstatus_e flags_parser() ;
- Xstatus_e disabled_parser() ;
- Xstatus_e rpc_number_parser() ;
- Xstatus_e nice_parser() ;
- X
- X/*
- X * A NULL value for the name field marks the end of the table
- X *
- X * The 3rd value is the number of attribute values.
- X * If the number is positive, exactly that many values must be specified.
- X * If the number is -1, 0 or more values may be specified.
- X * If the number is -2, 0 or more values may be specified and the operators
- X * '+=' and '-=' may be used.
- X */
- Xstatic struct attribute service_attributes[] =
- X {
- X { "socket_type", A_SOCKET_TYPE, 1, socket_type_parser },
- X { "protocol", A_PROTOCOL, 1, protocol_parser },
- X { "wait", A_WAIT, 1, wait_parser },
- X { "user", A_USER, 1, user_parser },
- X { "group", A_GROUP, 1, group_parser },
- X { "server", A_SERVER, 1, server_parser },
- X { "server_args", A_SERVER_ARGS, -1, server_args_parser },
- X { "instances", A_INSTANCES, 1, instances_parser },
- X { "log_on_success", A_LOG_ON_SUCCESS, -2, log_on_success_parser },
- X { "log_on_failure", A_LOG_ON_FAILURE, -2, log_on_failure_parser },
- X { "log_type", A_LOG_TYPE, -1, log_type_parser },
- X { "only_from", A_ONLY_FROM, -2, only_from_parser },
- X { "no_access", A_NO_ACCESS, -2, no_access_parser },
- X { "access_times", A_ACCESS_TIMES, -1, access_times_parser },
- X { "type", A_TYPE, -1, type_parser },
- X#ifndef NO_RPC
- X { "rpc_version", A_RPC_VERSION, 1, rpc_version_parser },
- X { "rpc_number", A_RPC_NUMBER, 1, rpc_number_parser },
- X#endif
- X { "id", A_ID, 1, id_parser },
- X { "env", A_ENV, -2, env_parser },
- X { "port", A_PORT, 1, port_parser },
- X { "passenv", A_PASSENV, -2, passenv_parser },
- X { "flags", A_FLAGS, -1, flags_parser },
- X { "nice", A_NICE, 1, nice_parser },
- X { NULL, A_NONE, -1, NULL }
- X } ;
- X
- Xstatic struct attribute default_attributes[] =
- X {
- X { "log_type", A_LOG_TYPE, -2, log_type_parser },
- X { "log_on_success", A_LOG_ON_SUCCESS, -2, log_on_success_parser },
- X { "log_on_failure", A_LOG_ON_FAILURE, -2, log_on_failure_parser },
- X { "disabled", A_DISABLED, -2, disabled_parser },
- X { "no_access", A_NO_ACCESS, -2, no_access_parser },
- X { "only_from", A_ONLY_FROM, -2, only_from_parser },
- X { "instances", A_INSTANCES, 1, instances_parser },
- X { "passenv", A_PASSENV, -2, passenv_parser },
- X { NULL, A_NONE, 0, NULL }
- X } ;
- X
- X
- X#define MODIFIABLE( ap ) ( (ap)->a_nvalues == -2 )
- X#define VAR_VALUES( ap ) ( (ap)->a_nvalues < 0 )
- X#define FIXED_VALUES( ap ) ( (ap)->a_nvalues > 0 )
- X
- Xint line_count ;
- X
- XPRIVATE void get_service_entry() ;
- XPRIVATE entry_e find_next_entry() ;
- XPRIVATE status_e parse_entry() ;
- X
- X
- X/*
- X * Given the id, return the name (only the service attributes are searched)
- X */
- Xchar *attr_name_lookup( id )
- X register int id ;
- X{
- X register struct attribute *ap ;
- X
- X for ( ap = &service_attributes[ 0 ] ; ap->a_name ; ap++ )
- X if ( id == ap->a_id )
- X return( ap->a_name ) ;
- X return( CHAR_NULL ) ;
- X}
- X
- X
- Xvoid parse_end()
- X{
- X endprotoent() ;
- X endpwent() ;
- X endgrent() ;
- X endnetent() ;
- X endhostent() ;
- X}
- X
- X
- X/*
- X * Parsing rules and rationale
- X *
- X * The parse_conf_file function parses a configuration file identified
- X * by a file descriptor and fills the service table and defaults of
- X * the configuration argument.
- X *
- X * The configuration information for a service comes from 2 sources: the
- X * service entry and, possibly, the defaults entry.
- X * Attributes specified in the defaults entry can be overriden or
- X * modified by the service entry. Modifiable attributes can be identified
- X * by the value -2 for the 'a_nvalues' field of the struct attribute. Those
- X * attributes with a different value for 'a_nvalues' are overridable ones.
- X * The modifiable attributes are filled in only if the entry tries to modify
- X * them.
- X */
- X
- X/*
- X * Read the configuration file (descriptor fd) and place all
- X * services found there in the configuration.
- X */
- Xvoid parse_conf_file( fd, confp )
- X int fd ;
- X struct configuration *confp ;
- X{
- X pset_h sconfs = CNF_SERVICE_CONFS( confp ) ;
- X struct service_config *default_config = CNF_DEFAULTS( confp ) ;
- X boolean_e found_defaults = NO ;
- X struct service_config default_default_config ;
- X char *func = "parse_conf_file" ;
- X
- X line_count = 0 ;
- X CLEAR( default_default_config ) ;
- X
- X for ( ;; )
- X {
- X entry_e entry_type ;
- X char *service_name ;
- X
- X /*
- X * if find_next_entry is successful, service_name
- X * will point to malloc'ed memory
- X */
- X entry_type = find_next_entry( fd, &service_name ) ;
- X
- X switch ( entry_type )
- X {
- X case SERVICE_ENTRY:
- X get_service_entry( fd, sconfs, service_name, default_config ) ;
- X break ;
- X
- X case DEFAULTS_ENTRY:
- X if ( found_defaults == YES )
- X {
- X parsemsg( LOG_ERR, func,
- X "only 1 defaults entry is allowed. This entry will be ignored" ) ;
- X skip_entry( fd ) ;
- X }
- X else if ( parse_entry( DEFAULTS_ENTRY, fd,
- X default_config, &default_default_config ) == OK )
- X found_defaults = YES ;
- X break ;
- X
- X case BAD_ENTRY:
- X skip_entry( fd ) ;
- X break ;
- X
- X case NO_ENTRY:
- X return ;
- X }
- X }
- X}
- X
- X
- X
- X/*
- X * Find the next service entry.
- X * Look for a line of the form:
- X *
- X * <white-space> service <white-space> <service_name>
- X *
- X * followed by a line containing only the ENTRY_BEGIN character
- X */
- XPRIVATE entry_e find_next_entry( fd, snamep )
- X int fd ;
- X char **snamep ; /* service name pointer */
- X{
- X register char *p ;
- X str_h strp ;
- X char *sname ;
- X entry_e entry_type ;
- X register char *line = next_line( fd ) ;
- X char *func = "find_next_entry" ;
- X
- X if ( line == CHAR_NULL )
- X return( NO_ENTRY ) ;
- X
- X strp = str_parse( line, " \t", STR_RETURN_ERROR, INT_NULL ) ;
- X if ( strp == NULL )
- X {
- X parsemsg( LOG_CRIT, func, "str_parse failed" ) ;
- X return( BAD_ENTRY ) ;
- X }
- X
- X if ( ( p = str_component( strp ) ) == CHAR_NULL )
- X {
- X /*
- X * This shouldn't happen since it implies that there is a bug
- X * in next_line
- X */
- X parsemsg( LOG_WARNING, func, "empty line" ) ;
- X str_endparse( strp ) ;
- X return( BAD_ENTRY ) ;
- X }
- X
- X /*
- X * Look for a keyword
- X */
- X if ( EQ( p, KW_SERVICE ) )
- X {
- X /*
- X * Now get the service name
- X */
- X if ( ( p = str_component( strp ) ) == CHAR_NULL )
- X {
- X parsemsg( LOG_ERR, func, "service name missing" ) ;
- X str_endparse( strp ) ;
- X return( BAD_ENTRY ) ;
- X }
- X
- X sname = make_string( 1, p ) ;
- X if ( sname == CHAR_NULL )
- X {
- X out_of_memory( func ) ;
- X str_endparse( strp ) ;
- X return( BAD_ENTRY ) ;
- X }
- X str_endparse( strp ) ;
- X entry_type = SERVICE_ENTRY ;
- X }
- X else if ( EQ( p, KW_DEFAULTS ) )
- X {
- X str_endparse( strp ) ;
- X entry_type = DEFAULTS_ENTRY ;
- X }
- X else
- X {
- X parsemsg( LOG_ERR, func, "missing service keyword" ) ;
- X str_endparse( strp ) ;
- X return( BAD_ENTRY ) ;
- X }
- X
- X /*
- X * Now look for ENTRY_BEGIN
- X */
- X line = next_line( fd ) ;
- X if ( line == NULL || ! line_has_only_1_char( line, ENTRY_BEGIN ) )
- X {
- X parsemsg( LOG_ERR, func,
- X "Service %s: missing '%c'", sname, ENTRY_BEGIN ) ;
- X if ( entry_type == SERVICE_ENTRY )
- X free( sname ) ;
- X return( BAD_ENTRY ) ;
- X }
- X *snamep = sname ;
- X return( entry_type ) ;
- X}
- X
- X
- X
- X/*
- X * Get a service entry. Steps:
- X *
- X * 1. Parse entry attributes
- X * 2. Determine service id
- X * 3. Insert entry in table
- X */
- XPRIVATE void get_service_entry( fd, sconfs, name, defaults )
- X int fd ;
- X pset_h sconfs ;
- X char *name ;
- X struct service_config *defaults ;
- X{
- X register struct service_config *scp ;
- X unsigned u ;
- X char *func = "get_service_entry" ;
- X
- X scp = sc_alloc( name ) ;
- X if ( scp == NULL )
- X {
- X free( name ) ;
- X skip_entry( fd ) ;
- X return ;
- X }
- X
- X if ( parse_entry( SERVICE_ENTRY, fd, scp, defaults ) == FAILED )
- X {
- X sc_free( scp ) ;
- X skip_entry( fd ) ;
- X return ;
- X }
- X
- X /*
- X * If no service id was specified, set it equal to the service name
- X */
- X if ( ! SC_SPECIFIED( scp, A_ID ) )
- X if ( scp->sc_id = make_string( 1, scp->sc_name ) )
- X SC_PRESENT( scp, A_ID ) ;
- X else
- X {
- X out_of_memory( func ) ;
- X sc_free( scp ) ;
- X return ;
- X }
- X
- X /*
- X * Make sure the service id is unique
- X */
- X for ( u = 0 ; u < pset_count( sconfs ) ; u++ )
- X if ( EQ( SCP( pset_pointer( sconfs, u ) )->sc_id, scp->sc_id ) )
- X {
- X parsemsg( LOG_ERR, func, "id not unique: %s", scp->sc_id ) ;
- X sc_free( scp ) ;
- X return ;
- X }
- X
- X if ( ! pset_add( sconfs, scp ) )
- X {
- X out_of_memory( func ) ;
- X sc_free( scp ) ;
- X return ;
- X }
- X}
- X
- X
- X
- X
- X/*
- X * Fill in scp the value of the modifiable attribute attr from def.
- X * These modifiable attributes are:
- X * log_on_{success,failure}
- X * only_from
- X * no_access
- X * passenv
- X */
- XPRIVATE void fill_attribute( attr_id, scp, def )
- X unsigned attr_id ;
- X struct service_config *scp ;
- X struct service_config *def ;
- X{
- X status_e copy_pset() ;
- X
- X switch ( attr_id )
- X {
- X case A_LOG_ON_SUCCESS:
- X M_ASSIGN( scp->sc_log_on_success, def->sc_log_on_success ) ;
- X SC_PRESENT( scp, A_LOG_ON_SUCCESS ) ;
- X break ;
- X
- X case A_LOG_ON_FAILURE:
- X M_ASSIGN( scp->sc_log_on_failure, def->sc_log_on_failure ) ;
- X SC_PRESENT( scp, A_LOG_ON_FAILURE ) ;
- X break ;
- X
- X case A_ONLY_FROM:
- X if ( addrlist_copy( def->sc_only_from, &scp->sc_only_from ) == OK )
- X SC_PRESENT( scp, A_ONLY_FROM ) ;
- X break ;
- X
- X case A_NO_ACCESS:
- X if ( addrlist_copy( def->sc_no_access, &scp->sc_no_access ) == OK )
- X SC_PRESENT( scp, A_NO_ACCESS ) ;
- X break ;
- X
- X case A_PASSENV:
- X if ( copy_pset( def->sc_pass_env_vars,
- X &scp->sc_pass_env_vars, 0 ) == OK )
- X SC_PRESENT( scp, A_PASSENV ) ;
- X break ;
- X }
- X}
- X
- X
- X
- X/*
- X * Find the attribute with the specified name
- X */
- XPRIVATE struct attribute *attr_lookup( attr_array, attr_name )
- X struct attribute attr_array[] ;
- X char *attr_name ;
- X{
- X register struct attribute *ap ;
- X char *func = "attr_lookup" ;
- X
- X for ( ap = &attr_array[ 0 ] ; ap->a_name ; ap++ )
- X if ( EQ( attr_name, ap->a_name ) )
- X return( ap ) ;
- X parsemsg( LOG_WARNING, func, "bad attribute: %s", attr_name ) ;
- X return( NULL ) ;
- X}
- X
- X
- X/*
- X * Identify the attribute in <attr_name>.
- X *
- X * Check if
- X * 1) the attribute has been defined already
- X * 2) the value count is correct
- X * 3) the assign op is appropriate
- X *
- X * Invoke appropriate parser
- X */
- XPRIVATE void identify_attribute( entry_type, scp, defaults,
- X attr_name, op, attr_values )
- X entry_e entry_type ;
- X struct service_config *scp ;
- X struct service_config *defaults ;
- X register char *attr_name ;
- X enum assign_op op ;
- X pset_h attr_values ;
- X{
- X register struct attribute *ap ;
- X char *func = "identify_attribute" ;
- X
- X if ( entry_type == SERVICE_ENTRY )
- X ap = attr_lookup( service_attributes, attr_name ) ;
- X else
- X ap = attr_lookup( default_attributes, attr_name ) ;
- X
- X if ( ap == NULL )
- X return ;
- X
- X if ( ! MODIFIABLE( ap ) )
- X {
- X if ( SC_SPECIFIED( scp, ap->a_id ) )
- X {
- X parsemsg( LOG_WARNING, func, "Service %s: attribute already set: %s",
- X scp->sc_name, attr_name ) ;
- X return ;
- X }
- X
- X if ( op != SET_EQ )
- X {
- X parsemsg( LOG_WARNING, func,
- X "Service %s: operator '%s' cannot be used for attribute '%s'",
- X scp->sc_name, ( op == PLUS_EQ ) ? "+=" : "-=", attr_name ) ;
- X return ;
- X }
- X }
- X else /* modifiable attribute */
- X {
- X /*
- X * For the defaults entry, '=' and '+=' have the same meaning
- X */
- X if ( entry_type == DEFAULTS_ENTRY && op == SET_EQ )
- X op = PLUS_EQ ;
- X
- X /*
- X * If this is the first time we see this attribute, and a default
- X * for it is available, copy that default.
- X */
- X if ( ! SC_IS_PRESENT( scp, ap->a_id ) &&
- X SC_SPECIFIED( defaults, ap->a_id ) )
- X fill_attribute( ap->a_id, scp, defaults ) ;
- X }
- X
- X if ( FIXED_VALUES( ap ) && ap->a_nvalues != pset_count( attr_values ) )
- X {
- X parsemsg( LOG_WARNING, func,
- X "attribute %s expects %d values and %d values were specified",
- X attr_name, ap->a_nvalues, pset_count( attr_values ) ) ;
- X return ;
- X }
- X
- X if ( (*ap->a_parser)( attr_values, scp, op ) == OK )
- X SC_SPECIFY( scp, ap->a_id ) ;
- X}
- X
- X
- X/*
- X * Read the entry line-by-line and add the information in scp
- X * Use defaults to initialize modifiable entry fields.
- X */
- XPRIVATE status_e parse_entry( entry_type, fd, scp, defaults )
- X entry_e entry_type ;
- X int fd ;
- X struct service_config *scp ;
- X struct service_config *defaults ;
- X{
- X static pset_h attr_values ;
- X register char *line ;
- X char *attr_name ;
- X enum assign_op op ;
- X void identify_attribute() ;
- X status_e parse_line() ;
- X char *func = "get_attributes" ;
- X
- X if ( ! attr_values && ( attr_values = pset_create( 10, 10 ) ) == NULL )
- X {
- X out_of_memory( func ) ;
- X return( FAILED ) ;
- X }
- X
- X for ( ;; )
- X {
- X line = next_line( fd ) ;
- X if ( line == CHAR_NULL )
- X {
- X parsemsg( LOG_ERR, func, "incomplete entry" ) ;
- X return( FAILED ) ;
- X }
- X
- X if ( line_has_only_1_char( line, ENTRY_END ) )
- X return( OK ) ;
- X
- X if ( parse_line( line, &attr_name, &op, attr_values ) == FAILED )
- X {
- X pset_clear( attr_values ) ;
- X return( FAILED ) ;
- X }
- X
- X identify_attribute( entry_type,
- X scp, defaults, attr_name, op, attr_values ) ;
- X pset_clear( attr_values ) ;
- X }
- X}
- X
- END_OF_FILE
- if test 14596 -ne `wc -c <'xinetd/parse.c'`; then
- echo shar: \"'xinetd/parse.c'\" unpacked with wrong size!
- fi
- # end of 'xinetd/parse.c'
- fi
- echo shar: End of archive 24 \(of 31\).
- cp /dev/null ark24isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 31 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-