Import upstream 2.3.14
[packages/xinetd.git] / libs / src / misc / m_env.c
1 /*
2  * (c) Copyright 1992 by Panagiotis Tsirigotis
3  * All rights reserved.  The file named COPYRIGHT specifies the terms 
4  * and conditions for redistribution.
5  */
6
7
8 #include "config.h"
9 #include <memory.h>
10 #include <string.h>
11 #include <stdlib.h>
12
13 #include "m_env.h"
14 #include "str.h"
15
16
17 typedef struct __env env_s ;
18
19 #define INITIAL_VARS            20
20 #define INCREASE                10
21
22
23 int env_errno ;
24
25 static char **lookup( const env_h env, const char *var, 
26         register unsigned int len );
27
28 static env_s *alloc_env( unsigned max_vars )
29 {
30    env_s *ep ;
31    unsigned size ;
32    char **pointers ;
33
34    ep = (env_s *) malloc( sizeof( env_s ) ) ;
35    if ( ep == ENV_NULL )
36    {
37       env_errno = ENV_ENOMEM ;
38       return( ENV_NULL ) ;
39    }
40
41    memset( ep, 0, sizeof( env_s ) );
42    size = ( max_vars + 1 ) * sizeof( char * ) ;
43    pointers = (char **) malloc( size ) ;
44    if ( pointers == NULL )
45    {
46       free( (char *)ep ) ;
47       env_errno = ENV_ENOMEM ;
48       return( ENV_NULL ) ;
49    }
50    (void) memset( (char *)pointers, 0, size ) ;
51
52    ep->vars = pointers ;
53    ep->max_vars = max_vars ;
54    ep->n_vars = 0 ;
55    return( ep ) ;
56 }
57
58
59 env_h env_create( const env_h init_env )
60 {
61    unsigned u ;
62    env_s *ep ;
63    unsigned max_vars ;
64
65    if ( init_env == ENV_NULL )
66       max_vars = INITIAL_VARS ;
67    else
68       max_vars = init_env->n_vars + 5 ;
69    
70    ep = alloc_env( max_vars ) ;
71    if ( ep == NULL )
72    {
73       env_errno = ENV_ENOMEM ;
74       return( ENV_NULL ) ;
75    }
76
77    if ( init_env == ENV_NULL )
78       return( ep ) ;
79
80    for ( u = 0, ep->n_vars = 0 ; u < init_env->n_vars ; u++, ep->n_vars++ )
81    {
82       ep->vars[ ep->n_vars ] = new_string( init_env->vars[ u ] ) ;
83       if ( ep->vars[ ep->n_vars ] == NULL )
84       {
85          env_destroy( ep ) ;
86          env_errno = ENV_ENOMEM ;
87          return( ENV_NULL ) ;
88       }
89    }
90    return( ep ) ;
91 }
92
93
94 void env_destroy( env_h env )
95 {
96    unsigned u ;
97
98    for ( u = 0 ; u < env->n_vars ; u++ )
99       free( env->vars[ u ] ) ;
100    free( (char *)env->vars ) ;
101    free( (char *)env ) ;
102 }
103
104
105 env_h env_make( char **env_strings )
106 {
107    env_s *ep ;
108    char **pp ;
109
110    for ( pp = env_strings ; *pp ; pp++ ) ;
111
112    ep = alloc_env( (unsigned) (pp-env_strings) ) ;
113    if ( ep == NULL )
114    {
115       env_errno = ENV_ENOMEM ;
116       return( ENV_NULL ) ;
117    }
118
119    for ( pp = env_strings ; *pp ; pp++ )
120    {
121       char *p = new_string( *pp ) ;
122
123       if ( p == NULL )
124       {
125          env_destroy( ep ) ;
126          env_errno = ENV_ENOMEM ;
127          return( ENV_NULL ) ;
128       }
129       ep->vars[ ep->n_vars++ ] = p ;
130    }
131    return( ep ) ;
132 }
133
134
135 char *env_lookup( env_h env, const char *var )
136 {
137    char **pp = lookup( env, var, strlen( var ) ) ;
138
139    return( ( pp == NULL ) ? NULL : *pp ) ;
140 }
141
142
143 static char **lookup( const env_h env, const char * var, 
144         register unsigned int len )
145 {
146    char **pp ;
147
148    for ( pp = env->vars ; *pp ; pp++ )
149       if ( strncmp( *pp, var, len ) == 0 && (*pp)[ len ] == '=' )
150          return( pp ) ;
151    return( NULL ) ;
152 }
153
154
155 static int grow( env_s *ep )
156 {
157    char **new_vars ;
158    unsigned new_max_vars ;
159    unsigned new_size ;
160    new_max_vars = ep->max_vars + INCREASE ;
161    new_size = ( new_max_vars+1 ) * sizeof( char * ) ;
162    new_vars = (char **) realloc( (char *)ep->vars, new_size ) ;
163    if ( new_vars == NULL )
164       return( ENV_ERR ) ;
165
166    ep->vars = new_vars ;
167    ep->max_vars = new_max_vars ;
168    
169    memset(&ep->vars[ep->n_vars], 0, new_size - (ep->n_vars * sizeof(char *)));
170    return( ENV_OK ) ;
171 }
172
173
174 /*
175  * Add the variable string to the given environment.
176  */
177 static int addstring( env_s *ep, const char *var_string, unsigned int len )
178 {
179    char **pp ;
180    char *p ;
181
182    p = new_string( var_string ) ;
183    if ( p == NULL )
184       return( ENV_ERR ) ;
185       
186    pp = lookup( ep, var_string, len ) ;
187    if ( pp == NULL )
188    {
189       if ( ep->n_vars >= ep->max_vars && grow( ep ) == ENV_ERR )
190       {
191          free( p ) ;
192          env_errno = ENV_ENOMEM ;
193          return( ENV_ERR ) ;
194       }
195       ep->vars[ ep->n_vars++ ] = p ;
196       ep->vars[ ep->n_vars ] = NULL;
197    }
198    else
199    {
200       free( *pp ) ;
201       *pp = p ;
202    }
203    return( ENV_OK ) ;
204 }
205
206
207 int env_addvar( env_h env, env_h from_env, char *var_name )
208 {
209    char *var_string = env_lookup( from_env, var_name ) ;
210
211    if ( var_string == NULL )
212    {
213       env_errno = ENV_EBADVAR ;
214       return( ENV_ERR ) ;
215    }
216
217    return( addstring( env, var_string, strlen( var_name ) ) ) ;
218 }
219
220
221 int env_addstr( env_h env, char *var_string )
222 {
223    char *p = strchr( var_string, '=' ) ;
224
225    if ( p == NULL )
226    {
227       env_errno = ENV_EBADSTRING ;
228       return( ENV_ERR ) ;
229    }
230
231    return( addstring( env, var_string, (unsigned int)(p-var_string) ) ) ;
232 }
233
234
235 #ifdef notdef
236 static int comparator( char **p1, char **p2 )
237 {
238    return( strcmp( *p1, *p2 ) ) ;
239 }
240
241
242 void env_sort( env_h env )
243 {
244    qsort( (char *)env->vars, env->n_vars, sizeof( char * ), comparator ) ;
245 }
246 #endif
247