source: set.c @ 7125cb3

Last change on this file since 7125cb3 was 7125cb3, checked in by Wilmer van der Gaast <wilmer@…>, at 2008-08-24T18:01:05Z

Added SET_INVALID, which set evaluators should now return instead of NULL
when the given value is not accepted. This to allow certain variables
actually be set to NULL (server, for example). This should fully close
#444.

  • Property mode set to 100644
File size: 5.7 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Some stuff to register, handle and save user preferences             */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
23  Suite 330, Boston, MA  02111-1307  USA
24*/
25#define BITLBEE_CORE
26#include "bitlbee.h"
27
28/* Used to use NULL for this, but NULL is actually a "valid" value. */
29char *SET_INVALID = "nee";
30
31set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data )
32{
33        set_t *s = set_find( head, key );
34       
35        /* Possibly the setting already exists. If it doesn't exist yet,
36           we create it. If it does, we'll just change the default. */
37        if( !s )
38        {
39                if( ( s = *head ) )
40                {
41                        while( s->next ) s = s->next;
42                        s->next = g_new0( set_t, 1 );
43                        s = s->next;
44                }
45                else
46                {
47                        s = *head = g_new0( set_t, 1 );
48                }
49                s->key = g_strdup( key );
50        }
51       
52        if( s->def )
53        {
54                g_free( s->def );
55                s->def = NULL;
56        }
57        if( def ) s->def = g_strdup( def );
58       
59        s->eval = eval;
60        s->data = data;
61       
62        return s;
63}
64
65set_t *set_find( set_t **head, char *key )
66{
67        set_t *s = *head;
68       
69        while( s )
70        {
71                if( g_strcasecmp( s->key, key ) == 0 )
72                        break;
73                s = s->next;
74        }
75       
76        return s;
77}
78
79char *set_getstr( set_t **head, char *key )
80{
81        set_t *s = set_find( head, key );
82       
83        if( !s || ( !s->value && !s->def ) )
84                return NULL;
85       
86        return s->value ? s->value : s->def;
87}
88
89int set_getint( set_t **head, char *key )
90{
91        char *s = set_getstr( head, key );
92        int i = 0;
93       
94        if( !s )
95                return 0;
96       
97        if( sscanf( s, "%d", &i ) != 1 )
98                return 0;
99       
100        return i;
101}
102
103int set_getbool( set_t **head, char *key )
104{
105        char *s = set_getstr( head, key );
106       
107        if( !s )
108                return 0;
109       
110        return bool2int( s );
111}
112
113int set_setstr( set_t **head, char *key, char *value )
114{
115        set_t *s = set_find( head, key );
116        char *nv = value;
117       
118        if( !s )
119                /*
120                Used to do this, but it never really made sense.
121                s = set_add( head, key, NULL, NULL, NULL );
122                */
123                return 0;
124       
125        if( value == NULL && ( s->flags & SET_NULL_OK ) == 0 )
126                return 0;
127       
128        /* Call the evaluator. For invalid values, evaluators should now
129           return SET_INVALID, but previously this was NULL. Try to handle
130           that too if NULL is not an allowed value for this setting. */
131        if( s->eval && ( ( nv = s->eval( s, value ) ) == SET_INVALID ||
132                         ( ( s->flags & SET_NULL_OK ) == 0 && nv == NULL ) ) )
133                return 0;
134       
135        if( s->value )
136        {
137                g_free( s->value );
138                s->value = NULL;
139        }
140       
141        /* If there's a default setting and it's equal to what we're trying to
142           set, stick with s->value = NULL. Otherwise, remember the setting. */
143        if( !s->def || ( strcmp( nv, s->def ) != 0 ) )
144                s->value = g_strdup( nv );
145       
146        if( nv != value )
147                g_free( nv );
148       
149        return 1;
150}
151
152int set_setint( set_t **head, char *key, int value )
153{
154        char s[24];     /* Not quite 128-bit clean eh? ;-) */
155       
156        g_snprintf( s, sizeof( s ), "%d", value );
157        return set_setstr( head, key, s );
158}
159
160void set_del( set_t **head, char *key )
161{
162        set_t *s = *head, *t = NULL;
163       
164        while( s )
165        {
166                if( g_strcasecmp( s->key, key ) == 0 )
167                        break;
168                s = (t=s)->next;
169        }
170        if( s )
171        {
172                if( t )
173                        t->next = s->next;
174                else
175                        *head = s->next;
176               
177                g_free( s->key );
178                if( s->value ) g_free( s->value );
179                if( s->def ) g_free( s->def );
180                g_free( s );
181        }
182}
183
184void set_reset( set_t **head, char *key )
185{
186        set_t *s;
187       
188        s = set_find( head, key );
189        if( s )
190                set_setstr( head, key, s->def );
191}
192
193char *set_eval_int( set_t *set, char *value )
194{
195        char *s = value;
196       
197        /* Allow a minus at the first position. */
198        if( *s == '-' )
199                s ++;
200       
201        for( ; *s; s ++ )
202                if( !isdigit( *s ) )
203                        return SET_INVALID;
204       
205        return value;
206}
207
208char *set_eval_bool( set_t *set, char *value )
209{
210        return is_bool( value ) ? value : SET_INVALID;
211}
212
213char *set_eval_to_char( set_t *set, char *value )
214{
215        char *s = g_new( char, 3 );
216       
217        if( *value == ' ' )
218                strcpy( s, " " );
219        else
220                sprintf( s, "%c ", *value );
221       
222        return s;
223}
224
225char *set_eval_ops( set_t *set, char *value )
226{
227        irc_t *irc = set->data;
228       
229        if( g_strcasecmp( value, "user" ) == 0 )
230                irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost,
231                                                              irc->channel, "+o-o", irc->nick, irc->mynick );
232        else if( g_strcasecmp( value, "root" ) == 0 )
233                irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost,
234                                                              irc->channel, "-o+o", irc->nick, irc->mynick );
235        else if( g_strcasecmp( value, "both" ) == 0 )
236                irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost,
237                                                              irc->channel, "+oo", irc->nick, irc->mynick );
238        else if( g_strcasecmp( value, "none" ) == 0 )
239                irc_write( irc, ":%s!%s@%s MODE %s %s %s %s", irc->mynick, irc->mynick, irc->myhost,
240                                                              irc->channel, "-oo", irc->nick, irc->mynick );
241        else
242                return SET_INVALID;
243       
244        return value;
245}
Note: See TracBrowser for help on using the repository browser.