fixes init script for non ipv6 enabled systems #472755
[packages/xinetd.git] / xinetd / parsesup.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * (c) Sections Copyright 1998-2001 by Rob Braun
4  * All rights reserved.  The file named COPYRIGHT specifies the terms 
5  * and conditions for redistribution.
6  */
7
8 #include "config.h"
9 #include <sys/types.h>
10 #ifdef HAVE_STDINT_H
11 #include <stdint.h>
12 #endif
13 #include <ctype.h>
14 #include <syslog.h>
15
16 #include "sio.h"
17 #include "str.h"
18 #include "parsesup.h"
19 #include "msg.h"
20
21
22 /*
23  * next_line returns the next line of the file or NULL if the end of file
24  * is reached.
25  * Comment lines and empty lines are skipped.
26  */
27 char *next_line( int fd )
28 {
29    for ( ;; )
30    {
31       char *p ;
32       char *line = Srdline( fd ) ;
33
34       if ( line == NULL )
35          return( NULL ) ;
36
37       line_count++ ;
38
39       for ( p = line ;; p++ )
40          if ( *p == NUL || *p == COMMENT_BEGIN )
41             break ;                                /* skip this line */
42          else if ( isspace( *p ) )
43             continue ;                             /* skip white space */
44          else
45             return( line ) ;
46    }
47 }
48
49
50 /*
51  * Input:
52  *      a line of the form
53  *            name [SPACE] OP [SPACE] value [SPACE] value ...
54  *
55  * Recognize the attribute name and operator and place them in *attrp, *opp
56  *
57  * Currently, we allow any non-space character to be used in the
58  * attribute name.
59  *
60  * Return value: a pointer to the character after OP.
61  */
62 static char *get_attr_op( char *line, char **attrp, enum assign_op *opp )
63 {
64    char            *p ;
65    char            *attr ;
66    enum assign_op   op ;
67    const char      *func = "get_attr_op" ;
68
69    /*
70     * First get the attribute name
71     */
72    for ( p = line ; isspace( *p ) ; p++ ) ;      /* skip spaces */
73    if ( *p == NUL )
74    {
75       parsemsg( LOG_ERR, func, "Empty line" ) ;
76       return( NULL ) ;
77    }
78
79    attr = p ;
80    for ( ; ! isspace( *p ) && (*p != '='); p++ ) ;            /* skip attribute name */
81    if ( *p == NUL )
82    {
83       parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ;
84       return( NULL ) ;
85    }
86    if( *p == '=' ) {
87       *p = NUL ;         /* now attribute name is NUL terminated */
88       parsemsg( LOG_ERR, func, "Attribute %s needs a space before operator", attr);
89       return( NULL ) ;
90    }
91    *p++ = NUL ;         /* now attribute name is NUL terminated */
92
93    while ( isspace( *p ) ) p++ ;      /* skip spaces */
94
95    switch ( *p )
96    {
97       case NUL:
98          parsemsg( LOG_ERR, func, "Nothing after attribute: %s", attr ) ;
99          return( NULL ) ;
100    
101       case '=':
102          op = SET_EQ ;
103          break ;
104       
105       case '+':
106       case '-':
107          op = ( *p++ == '+' ) ? PLUS_EQ : MINUS_EQ ;
108          if ( *p == '=' )
109             break ;
110          
111          /* FALL THROUGH if there is no '=' after the '+' or '-' */
112       
113       default:
114          parsemsg( LOG_ERR, func, "Bad operator for attribute: %s", attr ) ;
115          return( NULL ) ;
116    }
117    *attrp = attr ;
118    *opp = op ;
119    return( ++p ) ;      /* skip the '=' */
120 }
121
122
123 /*
124  * Parse a line of the form:
125  *         name OP value value value ...
126  * where each value is a string and OP can be '=', '+=', '-='
127  *
128  * NOTE: We do not allocate space for the name and values. Instead we keep
129  *         pointers to the line.
130  */
131 status_e parse_line( char *line, 
132                      char **namep, 
133                      enum assign_op *opp, 
134                      pset_h values )
135 {
136    char      *value ;
137    char      *values_string ;
138    char      *attribute ;
139    str_h    strp ;
140    const char *func = "parse_line" ;
141
142    if ( ( values_string = get_attr_op( line, &attribute, opp ) ) == NULL )
143       return( FAILED ) ;
144
145    /*
146     * Now grab the values
147     */
148    strp = str_parse( values_string, " \t", STR_RETURN_ERROR, (int *)0 ) ;
149    if ( strp == NULL )
150    {
151       parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
152       return( FAILED ) ;
153    }
154
155    while ( (value = str_component( strp )) )
156    {
157       if ( pset_add( values, value ) == NULL )
158       {
159          parsemsg( LOG_CRIT, func, ES_NOMEM ) ;
160          str_endparse( strp ) ;
161          return( FAILED ) ;
162       }
163    }
164
165    str_endparse( strp ) ;
166    *namep = attribute ;
167    return( OK ) ;
168 }
169
170
171 void skip_entry( int fd )
172 {
173    for ( ;; )
174    {
175       char *line = next_line( fd ) ;
176
177       if ( line == NULL )         /* reached EOF ? */
178       {
179          parsemsg( LOG_WARNING, "skip_entry",
180             "missing %c in last service entry", ENTRY_END ) ;
181          break ;
182       }
183
184       if ( line_has_only_1_char( line, ENTRY_END ) )
185          break ;
186    }
187 }
188
189
190
191 /*
192  * Returns TRUE if the given line contains a single instance of the
193  * specified character and no other non-space characters
194  */
195 int line_has_only_1_char( const char *line, char ch )
196 {
197    const char *p ;
198    char target_char = ch ;
199
200    for ( p = line ; *p ; p++ )
201       if ( *p == target_char )
202          target_char = NUL ;
203       else if ( ! isspace( *p ) )
204          return( FALSE ) ;
205    return( target_char != ch ) ;
206 }
207