source: variable.c @ 1e6e74e

debianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1e6e74e was 81a96af, checked in by Nelson Elhage <nelhage@mit.edu>, 16 years ago
Update the docs on 'zsig' and 'zsigproc'. Correctly document the order in which they are checked for values before being used. fixes #74 Reported-By: Xavid Pretzer <xavid@mit.edu>
  • Property mode set to 100644
File size: 38.8 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <ctype.h>
6#include "owl.h"
7
8static const char fileIdent[] = "$Id$";
9
10static int in_regtest = 0;
11
12#define OWLVAR_BOOL(name,default,summary,description) \
13        { name, OWL_VARIABLE_BOOL, NULL, default, "on,off", summary,description, NULL, \
14        NULL, NULL, NULL, NULL, NULL }
15
16#define OWLVAR_BOOL_FULL(name,default,summary,description,validate,set,get) \
17        { name, OWL_VARIABLE_BOOL, NULL, default, "on,off", summary,description, NULL, \
18        validate, set, NULL, get, NULL }
19
20#define OWLVAR_INT(name,default,summary,description) \
21        { name, OWL_VARIABLE_INT, NULL, default, "<int>", summary,description, NULL, \
22        NULL, NULL, NULL, NULL, NULL, NULL }
23
24#define OWLVAR_INT_FULL(name,default,summary,description,validset,validate,set,get) \
25        { name, OWL_VARIABLE_INT, NULL, default, validset, summary,description, NULL, \
26        validate, set, NULL, get, NULL, NULL }
27
28#define OWLVAR_PATH(name,default,summary,description) \
29        { name, OWL_VARIABLE_STRING, default, 0, "<path>", summary,description,  NULL, \
30        NULL, NULL, NULL, NULL, NULL, NULL }
31
32#define OWLVAR_STRING(name,default,summary,description) \
33        { name, OWL_VARIABLE_STRING, default, 0, "<string>", summary,description, NULL, \
34        NULL, NULL, NULL, NULL, NULL, NULL }
35
36#define OWLVAR_STRING_FULL(name,default,summary,description,validate,set,get) \
37        { name, OWL_VARIABLE_STRING, default, 0, "<string>", summary,description, NULL, \
38        validate, set, NULL, get, NULL, NULL }
39
40/* enums are really integers, but where validset is a comma-separated
41 * list of strings which can be specified.  The tokens, starting at 0,
42 * correspond to the values that may be specified. */
43#define OWLVAR_ENUM(name,default,summary,description,validset) \
44        { name, OWL_VARIABLE_INT, NULL, default, validset, summary,description, NULL, \
45        owl_variable_enum_validate, \
46        NULL, owl_variable_enum_set_fromstring, \
47        NULL, owl_variable_enum_get_tostring, \
48        NULL }
49
50#define OWLVAR_ENUM_FULL(name,default,summary,description,validset,validate, set, get) \
51        { name, OWL_VARIABLE_INT, NULL, default, validset, summary,description, NULL, \
52        validate, \
53        set, owl_variable_enum_set_fromstring, \
54        get, owl_variable_enum_get_tostring, \
55        NULL }
56
57static owl_variable variables_to_init[] = {
58
59  OWLVAR_STRING( "personalbell" /* %OwlVarStub */, "off",
60                 "ring the terminal bell when personal messages are received",
61                 "Can be set to 'on', 'off', or the name of a filter which\n"
62                 "messages need to match in order to ring the bell"),
63
64  OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1,
65               "enable / disable the terminal bell", "" ),
66
67  OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG,
68                    "whether debugging is enabled",
69                    "If set to 'on', debugging messages are logged to the\n"
70                    "file specified by the debugfile variable.\n",
71                    NULL, owl_variable_debug_set, NULL),
72
73  OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1,
74               "send a login message when owl starts", "" ),
75
76  OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1,
77               "send a logout message when owl exits", "" ),
78
79  OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0,
80               "display received pings", "" ),
81
82  OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1,
83               "send pings", "" ),
84
85  OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0,
86               "disable printing information in the separator bar", "" ),
87
88  OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1,
89               "strip kerberos instance for reply", ""),
90
91  OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1,
92               "strip leading and trailing newlines", ""),
93
94  OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1,
95               "display outgoing messages", "" ),
96
97  OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1,
98               "load logins from .anyone on startup", "" ),
99
100  OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0,
101               "turn personal logging on or off", 
102               "If this is set to on, personal messages are\n"
103               "logged in the directory specified\n"
104               "by the 'logpath' variable.  The filename in that\n"
105               "directory is derived from the sender of the message.\n" ),
106
107  OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0,
108               "turn class logging on or off",
109               "If this is set to on, class messages are\n"
110               "logged in the directory specified\n"
111               "by the 'classlogpath' variable.\n" 
112               "The filename in that directory is derived from\n"
113               "the name of the class to which the message was sent.\n" ),
114
115  OWLVAR_ENUM( "loggingdirection" /* %OwlVarStub */, OWL_LOGGING_DIRECTION_BOTH,
116               "specifices which kind of messages should be logged",
117               "Can be one of 'both', 'in', or 'out'.  If 'in' is\n"
118               "selected, only incoming messages are logged, if 'out'\n"
119               "is selected only outgoing messages are logged.  If 'both'\n"
120               "is selected both incoming and outgoing messages are\n"
121               "logged.",
122               "both,in,out"),
123
124  OWLVAR_BOOL( "colorztext" /* %OwlVarStub */, 1,
125               "allow @color() in zephyrs to change color",
126               "Note that only messages received after this variable\n"
127               "is set will be affected." ),
128
129  OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1,
130               "Use 'nice' line drawing on the terminal.",
131               "If turned off, dashes, pipes and pluses will be used\n"
132               "to draw lines on the screen.  Useful when the terminal\n"
133               "is causing problems" ),
134
135  OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
136               "Do automatic zcrypt processing",
137               "" ),
138
139  OWLVAR_BOOL_FULL( "pseudologins" /* %OwlVarStub */, 0,
140                    "Enable zephyr pseudo logins",
141                    "When this is enabled, Owl will periodically check the zephyr\n"
142                    "location of users in your .anyone file.  If a user is present\n"
143                    "but sent no login message, or a user is not present that sent no\n"
144                    "logout message, a pseudo login or logout message wil be created\n",
145                    NULL, owl_variable_pseudologins_set, NULL),
146
147  OWLVAR_BOOL( "ignorelogins" /* %OwlVarStub */, 0,
148               "Enable printing of login notifications",
149               "When this is enabled, Owl will print login and logout notifications\n"
150               "for AIM, zephyr, or other protocols.  If disabled Owl will not print\n"
151               "login or logout notifications.\n"),
152
153  OWLVAR_STRING( "logfilter" /* %OwlVarStub */, "",
154                 "name of a filter controlling which messages to log",
155
156                 "If non empty, any messages matching the given filter will be logged.\n"
157                 "This is a completely separate mechanisim from the other logging\n"
158                 "variables like logging, classlogging, loglogins, loggingdirection,\n"
159                 "etc.  If you want this variable to control all logging, make sure\n"
160                 "all other logging variables are in their default state.\n"),
161
162  OWLVAR_BOOL( "loglogins" /* %OwlVarStub */, 0,
163               "Enable logging of login notifications",
164               "When this is enabled, Owl will login login and logout notifications\n"
165               "for AIM, zephyr, or other protocols.  If disabled Owl will not print\n"
166               "login or logout notifications.\n"),
167
168  OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
169                    "don't send zephyrs on C-d",
170                    "If set to 'off', C-d won't send a zephyr from the edit\n"
171                    "window.  If set to 'on', C-d will always send a zephyr\n"
172                    "being composed in the edit window.  If set to 'middle',\n"
173                    "C-d will only ever send a zephyr if the cursor is at\n"
174                    "the end of the message being composed.\n\n"
175                    "Note that this works by changing the C-d keybinding\n"
176                    "in the editmulti keymap.\n",
177                    "off,middle,on",
178                    NULL, owl_variable_disable_ctrl_d_set, NULL),
179
180  OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",
181               "path for logging personal zephyrs", 
182               "Specifies a directory which must exist.\n"
183               "Files will be created in the directory for each sender.\n"),
184
185  OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",
186               "path for logging class zephyrs",
187               "Specifies a directory which must exist.\n"
188               "Files will be created in the directory for each class.\n"),
189
190  OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
191               "path for logging debug messages when debugging is enabled",
192               "This file will be logged to if 'debug' is set to 'on'.\n"),
193 
194  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
195               "name of a program to run that will generate zsigs",
196               "This program should produce a zsig on stdout when run.\n"
197               "Note that it is important that this program not block.\n\n"
198               "See the documentation for 'zsig' for more information about\n"
199               "how the outgoing zsig is chosen."
200               ),
201
202  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
203               "name of a program to run when new messages are present",
204               "The named program will be run when owl recevies new.\n"
205               "messages.  It will not be run again until the first\n"
206               "instance exits"),
207
208  OWLVAR_STRING( "zsender" /* %OwlVarStub */, "",
209             "zephyr sender name",
210         "Allows you to customize the outgoing username in\n"
211         "zephyrs.  If this is unset, it will use your Kerberos\n"
212         "principal. Note that customizing the sender name will\n"
213         "cause your zephyrs to be sent unauthenticated."),
214
215  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
216                 "zephyr signature",
217                 "The zsig to get on outgoing messages. If this variable is\n"
218                 "unset, 'zsigproc' will be run to generate a zsig. If that is\n"
219                 "also unset, the 'zwrite-signature' zephyr variable will be\n"
220                 "used instead.\n"),
221
222  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
223                 "string to append to the end of the sepbar",
224                 "The sepbar is the bar separating the top and bottom\n"
225                 "of the owl screen.  Any string specified here will\n"
226                 "be displayed on the right of the sepbar\n"),
227
228  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
229               "turn zaway on or off", "" ),
230
231  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
232                 OWL_DEFAULT_ZAWAYMSG,
233                 "zaway msg for responding to zephyrs when away", "" ),
234
235  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
236                 OWL_DEFAULT_ZAWAYMSG,
237                 "default zaway message", "" ),
238
239  OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,
240                    "Set AIM away status",
241                    "",
242                    NULL, owl_variable_aaway_set, NULL),
243
244  OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, 
245                 OWL_DEFAULT_AAWAYMSG,
246                 "AIM away msg for responding when away", "" ),
247
248  OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, 
249                 OWL_DEFAULT_AAWAYMSG,
250                 "default AIM away message", "" ),
251
252  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
253                 "home view to switch to after 'X' and 'V'", 
254                 "SEE ALSO: view, filter\n" ),
255
256  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
257                 "filter on which to trigger alert actions",
258                 "" ),
259
260  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
261                 "owl command to execute for alert actions",
262                 "" ),
263
264  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
265                      NULL, owl_variable_tty_set, NULL),
266
267  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "__unspecified__",
268                 "name of the default formatting style",
269                 "This sets the default message formatting style.\n"
270                 "Styles may be created with the 'style' command.\n"
271                 "Some built-in styles include:\n"
272                 "   default  - the default owl formatting\n"
273                 "   oneline  - one line per-message\n"
274                 "   perl     - legacy perl interface\n"
275                 "\nSEE ALSO: style, show styles, view -s <style>\n"
276                 ),
277
278
279  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
280                 "maximum number of columns for M-q to fill text to",
281                 "This specifies the maximum number of columns for M-q\n"
282                 "to fill text to.  If set to 0, ther will be no maximum\n"
283                 "limit.  In all cases, the current width of the screen\n"
284                 "will also be taken into account.  It will be used instead\n"
285                 "if it is narrower than the maximum, or if this\n"
286                 "is set to 0.\n" ),
287
288  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 0,
289                 "maximum number of columns for line-wrapping",
290                 "This specifies the maximum number of columns for\n"
291                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
292                 "limit.  In all cases, the current width of the screen\n"
293                 "will also be taken into account.  It will be used instead\n"
294                 "if it is narrower than the maximum, or if this\n"
295                 "is set to 0.\n\n"
296                 "It is recommended that outgoing messages be no wider\n"
297                 "than 60 columns, as a courtesy to recipients.\n"),
298
299  OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 15,
300              "number of seconds after AIM login to ignore login messages",
301              "This specifies the number of seconds to wait after an\n"
302              "AIM login before allowing the recipt of AIM login notifications.\n"
303              "By default this is set to 15.  If you would like to view login\n"
304              "notifications of buddies as soon as you login, set it to 0 instead."),
305
306             
307  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
308                   OWL_TYPWIN_SIZE,
309                  "number of lines in the typing window", 
310                   "This specifies the height of the window at the\n"
311                   "bottom of the screen where commands are entered\n"
312                   "and where messages are composed.\n",
313                   "int > 0",
314                   owl_variable_int_validate_gt0,
315                   owl_variable_typewinsize_set,
316                   NULL /* use default for get */
317                   ),
318
319  OWLVAR_INT( "typewindelta" /* %OwlVarStub */, 0,
320                  "number of lines to add to the typing window when in use",
321                   "On small screens you may want the typing window to\n"
322                   "auto-hide when not entering a command or message.\n"
323                   "This variable is the number of lines to add to the\n"
324           "typing window when it is in use; you can then set\n"
325           "typewinsize to 1.\n\n"
326           "This works a lot better with a non-default scrollmode;\n"
327           "try :set scrollmode pagedcenter.\n"),
328
329  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
330               "how to scroll up and down",
331               "This controls how the screen is scrolled as the\n"
332               "cursor moves between messages being displayed.\n"
333               "The following modes are supported:\n\n"
334               "   normal      - This is the owl default.  Scrolling happens\n"
335               "                 when it needs to, and an attempt is made to\n"
336               "                 keep the current message roughly near\n"
337               "                 the middle of the screen.\n"
338               "   top         - The current message will always be the\n"
339               "                 the top message displayed.\n"
340               "   neartop     - The current message will be one down\n"
341               "                 from the top message displayed,\n"
342               "                 where possible.\n"
343               "   center      - An attempt is made to keep the current\n"
344               "                 message near the center of the screen.\n"
345               "   paged       - The top message displayed only changes\n"
346               "                 when user moves the cursor to the top\n"
347               "                 or bottom of the screen.  When it moves,\n"
348               "                 the screen will be paged up or down and\n"
349               "                 the cursor will be near the top or\n"
350               "                 the bottom.\n"
351               "   pagedcenter - The top message displayed only changes\n"
352               "                 when user moves the cursor to the top\n"
353               "                 or bottom of the screen.  When it moves,\n"
354               "                 the screen will be paged up or down and\n"
355               "                 the cursor will be near the center.\n",
356               "normal,top,neartop,center,paged,pagedcenter" ),
357
358
359  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
360               "enable automatic following of the last zephyr",
361               "If the cursor is at the last message, it will\n"
362               "continue to follow the last message if this is set.\n"
363               "Note that this is currently risky as you might accidentally\n"
364               "delete a message right as it came in.\n" ),
365
366  /* This MUST be last... */
367  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
368    NULL, NULL, NULL, NULL, NULL, NULL }
369
370};
371
372/**************************************************************************/
373/*********************** SPECIFIC TO VARIABLES ****************************/
374/**************************************************************************/
375
376
377/* commonly useful */
378
379int owl_variable_int_validate_gt0(owl_variable *v, void *newval)
380{
381  if (newval == NULL) return(0);
382  else if (*(int*)newval < 1) return(0);
383  else return (1);
384}
385
386int owl_variable_int_validate_positive(owl_variable *v, void *newval)
387{
388  if (newval == NULL) return(0);
389  else if (*(int*)newval < 0) return(0);
390  else return (1);
391}
392
393/* typewinsize */
394int owl_variable_typewinsize_set(owl_variable *v, void *newval)
395{
396  int rv;
397  rv = owl_variable_int_set_default(v, newval);
398  if (0 == rv) owl_function_resize();
399  return(rv);
400}
401
402/* debug (cache value in g->debug) */
403int owl_variable_debug_set(owl_variable *v, void *newval)
404{
405  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
406    g.debug = *(int*)newval;
407  }
408  return owl_variable_bool_set_default(v, newval);
409}
410
411/* When 'aaway' is changed, need to notify the AIM server */
412int owl_variable_aaway_set(owl_variable *v, void *newval)
413{
414  if (newval) {
415    if (*(int*)newval == 1) {
416      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
417    } else if (*(int*)newval == 0) {
418      owl_aim_set_awaymsg("");
419    }
420  }
421  return owl_variable_bool_set_default(v, newval);
422}
423
424int owl_variable_pseudologins_set(owl_variable *v, void *newval)
425{
426  if (newval) {
427    if (*(int*)newval == 1) {
428      owl_function_zephyr_buddy_check(0);
429    }
430  }
431  return owl_variable_bool_set_default(v, newval);
432}
433
434/* note that changing the value of this will clobber
435 * any user setting of this */
436int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval)
437{
438
439  if (in_regtest) return owl_variable_int_set_default(v, newval);
440
441  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
442    if (*(int*)newval == 2) {
443      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
444    } else if (*(int*)newval == 1) {
445      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
446    } else {
447      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
448    }
449  } 
450  return owl_variable_int_set_default(v, newval); 
451}
452
453int owl_variable_tty_set(owl_variable *v, void *newval)
454{
455  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
456  return(owl_variable_string_set_default(v, newval));
457}
458
459
460/**************************************************************************/
461/****************************** GENERAL ***********************************/
462/**************************************************************************/
463
464int owl_variable_dict_setup(owl_vardict *vd) {
465  owl_variable *var, *cur;
466  if (owl_dict_create(vd)) return(-1);
467  for (var = variables_to_init; var->name != NULL; var++) {
468    cur = owl_malloc(sizeof(owl_variable));
469    memcpy(cur, var, sizeof(owl_variable));
470    switch (cur->type) {
471    case OWL_VARIABLE_OTHER:
472      cur->set_fn(cur, cur->pval_default);
473      break;
474    case OWL_VARIABLE_STRING:
475      if (!cur->validate_fn) 
476        cur->validate_fn = owl_variable_string_validate_default;
477      if (!cur->set_fn) 
478        cur->set_fn = owl_variable_string_set_default;
479      if (!cur->set_fromstring_fn) 
480        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
481      if (!cur->get_fn) 
482        cur->get_fn = owl_variable_get_default;
483      if (!cur->get_tostring_fn) 
484        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
485      if (!cur->free_fn) 
486        cur->free_fn = owl_variable_free_default;
487      cur->set_fn(cur, cur->pval_default);
488      break;
489    case OWL_VARIABLE_BOOL:
490      if (!cur->validate_fn) 
491        cur->validate_fn = owl_variable_bool_validate_default;
492      if (!cur->set_fn) 
493        cur->set_fn = owl_variable_bool_set_default;
494      if (!cur->set_fromstring_fn) 
495        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
496      if (!cur->get_fn) 
497        cur->get_fn = owl_variable_get_default;
498      if (!cur->get_tostring_fn) 
499        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
500      if (!cur->free_fn) 
501        cur->free_fn = owl_variable_free_default;
502      cur->val = owl_malloc(sizeof(int));
503      cur->set_fn(cur, &cur->ival_default);
504      break;
505    case OWL_VARIABLE_INT:
506      if (!cur->validate_fn) 
507        cur->validate_fn = owl_variable_int_validate_default;
508      if (!cur->set_fn) 
509        cur->set_fn = owl_variable_int_set_default;
510      if (!cur->set_fromstring_fn) 
511        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
512      if (!cur->get_fn) 
513        cur->get_fn = owl_variable_get_default;
514      if (!cur->get_tostring_fn) 
515        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
516      if (!cur->free_fn) 
517        cur->free_fn = owl_variable_free_default;
518      cur->val = owl_malloc(sizeof(int));
519      cur->set_fn(cur, &cur->ival_default);
520      break;
521    default:
522      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
523      return(-2);
524    }
525    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
526  }
527  return 0;
528}
529
530void owl_variable_dict_add_variable(owl_vardict * vardict,
531                                    owl_variable * var) {
532  owl_dict_insert_element(vardict, var->name, (void*)var, (void(*)(void*))owl_variable_free);
533}
534
535owl_variable * owl_variable_newvar(char *name, char *summary, char * description) {
536  owl_variable * var = (owl_variable*)owl_malloc(sizeof(owl_variable));
537  memset(var, 0, sizeof(owl_variable));
538  var->name = owl_strdup(name);
539  var->summary = owl_strdup(summary);
540  var->description = owl_strdup(description);
541  return var;
542}
543
544void owl_variable_update(owl_variable *var, char *summary, char *desc) {
545  if(var->summary) owl_free(var->summary);
546  var->summary = owl_strdup(summary);
547  if(var->description) owl_free(var->description);
548  var->description = owl_strdup(desc);
549}
550
551void owl_variable_dict_newvar_string(owl_vardict * vd, char *name, char *summ, char * desc, char * initval) {
552  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_STRING);
553  if(old) {
554    owl_variable_update(old, summ, desc);
555    if(old->pval_default) owl_free(old->pval_default);
556    old->pval_default = owl_strdup(initval);
557  } else {
558    owl_variable * var = owl_variable_newvar(name, summ, desc);
559    var->type = OWL_VARIABLE_STRING;
560    var->pval_default = owl_strdup(initval);
561    var->set_fn = owl_variable_string_set_default;
562    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
563    var->get_fn = owl_variable_get_default;
564    var->get_tostring_fn = owl_variable_string_get_tostring_default;
565    var->free_fn = owl_variable_free_default;
566    var->set_fn(var, initval);
567    owl_variable_dict_add_variable(vd, var);
568  }
569}
570
571void owl_variable_dict_newvar_int(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
572  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_INT);
573  if(old) {
574    owl_variable_update(old, summ, desc);
575    old->ival_default = initval;
576  } else {
577    owl_variable * var = owl_variable_newvar(name, summ, desc);
578    var->type = OWL_VARIABLE_INT;
579    var->ival_default = initval;
580    var->validate_fn = owl_variable_int_validate_default;
581    var->set_fn = owl_variable_int_set_default;
582    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
583    var->get_fn = owl_variable_get_default;
584    var->get_tostring_fn = owl_variable_int_get_tostring_default;
585    var->free_fn = owl_variable_free_default;
586    var->val = owl_malloc(sizeof(int));
587    var->set_fn(var, &initval);
588    owl_variable_dict_add_variable(vd, var);
589  }
590}
591
592void owl_variable_dict_newvar_bool(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
593  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_BOOL);
594  if(old) {
595    owl_variable_update(old, summ, desc);
596    old->ival_default = initval;
597  } else {
598    owl_variable * var = owl_variable_newvar(name, summ, desc);
599    var->type = OWL_VARIABLE_BOOL;
600    var->ival_default = initval;
601    var->validate_fn = owl_variable_bool_validate_default;
602    var->set_fn = owl_variable_bool_set_default;
603    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
604    var->get_fn = owl_variable_get_default;
605    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
606    var->free_fn = owl_variable_free_default;
607    var->val = owl_malloc(sizeof(int));
608    var->set_fn(var, &initval);
609    owl_variable_dict_add_variable(vd, var);
610  }
611}
612
613void owl_variable_dict_free(owl_vardict *d) {
614  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
615}
616
617/* free the list with owl_variable_dict_namelist_free */
618void owl_variable_dict_get_names(owl_vardict *d, owl_list *l) {
619  owl_dict_get_keys(d, l);
620}
621
622void owl_variable_dict_namelist_free(owl_list *l) {
623  owl_list_free_all(l, owl_free);
624}
625
626void owl_variable_free(owl_variable *v) {
627  if (v->free_fn) v->free_fn(v);
628  owl_free(v);
629}
630
631
632char *owl_variable_get_description(owl_variable *v) {
633  return v->description;
634}
635
636char *owl_variable_get_summary(owl_variable *v) {
637  return v->summary;
638}
639
640char *owl_variable_get_validsettings(owl_variable *v) {
641  if (v->validsettings) {
642    return v->validsettings;
643  } else {
644    return "";
645  }
646}
647
648/* functions for getting and setting variable values */
649
650/* returns 0 on success, prints a status msg if msg is true */
651int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
652  owl_variable *v;
653  char buff2[1024];
654  if (!name) return(-1);
655  v = owl_dict_find_element(d, name);
656  if (v == NULL) {
657    if (msg) owl_function_error("Unknown variable %s", name);
658    return -1;
659  }
660  if (!v->set_fromstring_fn) {
661    if (msg) owl_function_error("Variable %s is read-only", name);
662    return -1;   
663  }
664  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
665    if (msg) owl_function_error("Variable %s is not a boolean", name);
666    return -1;   
667  }
668  if (0 != v->set_fromstring_fn(v, value)) {
669    if (msg) owl_function_error("Unable to set %s (must be %s)", name, 
670                                  owl_variable_get_validsettings(v));
671    return -1;
672  }
673  if (msg && v->get_tostring_fn) {
674    v->get_tostring_fn(v, buff2, 1024, v->val);
675    owl_function_makemsg("%s = '%s'", name, buff2);
676  }   
677  return 0;
678}
679 
680int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
681  owl_variable *v;
682  if (!name) return(-1);
683  v = owl_dict_find_element(d, name);
684  if (v == NULL || !v->set_fn) return(-1);
685  if (v->type!=OWL_VARIABLE_STRING) return(-1);
686  return v->set_fn(v, (void*)newval);
687}
688 
689int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
690  owl_variable *v;
691  if (!name) return(-1);
692  v = owl_dict_find_element(d, name);
693  if (v == NULL || !v->set_fn) return(-1);
694  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
695  return v->set_fn(v, &newval);
696}
697 
698int owl_variable_set_bool_on(owl_vardict *d, char *name) {
699  return owl_variable_set_int(d,name,1);
700}
701
702int owl_variable_set_bool_off(owl_vardict *d, char *name) {
703  return owl_variable_set_int(d,name,0);
704}
705
706int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
707  owl_variable *v;
708  if (!name) return(-1);
709  v = owl_dict_find_element(d, name);
710  if (v == NULL || !v->get_tostring_fn) return(-1);
711  return v->get_tostring_fn(v, buf, bufsize, v->val);
712}
713
714int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
715  owl_variable *v;
716  if (!name) return(-1);
717  v = owl_dict_find_element(d, name);
718  if (v == NULL || !v->get_tostring_fn) return(-1);
719  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
720    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
721  } else {
722    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
723  }
724}
725
726owl_variable *owl_variable_get_var(owl_vardict *d, char *name, int require_type) {
727  owl_variable *v;
728  if (!name) return(NULL);
729  v = owl_dict_find_element(d, name);
730  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
731  return v;
732}
733
734/* returns a reference */
735void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
736  owl_variable *v = owl_variable_get_var(d, name, require_type);
737  if(v == NULL) return NULL;
738  return v->get_fn(v);
739}
740
741/* returns a reference */
742char *owl_variable_get_string(owl_vardict *d, char *name) {
743  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
744}
745
746/* returns a reference */
747void *owl_variable_get_other(owl_vardict *d, char *name) {
748  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
749}
750
751int owl_variable_get_int(owl_vardict *d, char *name) {
752  int *pi;
753  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
754  if (!pi) return(-1);
755  return(*pi);
756}
757
758int owl_variable_get_bool(owl_vardict *d, char *name) {
759  int *pi;
760  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
761  if (!pi) return(-1);
762  return(*pi);
763}
764
765void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
766  char defaultbuf[50];
767  char buf[1024];
768  int buflen = 1023;
769  owl_variable *v;
770
771  if (!name
772      || (v = owl_dict_find_element(d, name)) == NULL 
773      || !v->get_fn) {
774    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
775    owl_fmtext_append_normal(fm, buf);
776    return;
777  }
778  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
779    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
780  } else {
781    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
782  }
783  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
784                  v->name, 
785                  owl_variable_get_summary(v), defaultbuf);
786  owl_fmtext_append_normal(fm, buf);
787}
788
789void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
790  char buff[1024];
791  int bufflen = 1023;
792  owl_variable *v;
793
794  if (!name
795      || (v = owl_dict_find_element(d, name)) == NULL 
796      || !v->get_fn) {
797    owl_fmtext_append_normal(fm, "No such variable...\n");
798    return;
799  }
800
801  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
802  owl_fmtext_append_normal(fm, OWL_TABSTR);
803  owl_fmtext_append_normal(fm, name);
804  owl_fmtext_append_normal(fm, " - ");
805  owl_fmtext_append_normal(fm, v->summary);
806  owl_fmtext_append_normal(fm, "\n\n");
807
808  owl_fmtext_append_normal(fm, "Current:        ");
809  owl_variable_get_tostring(d, name, buff, bufflen);
810  owl_fmtext_append_normal(fm, buff);
811  owl_fmtext_append_normal(fm, "\n\n");
812
813
814  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
815    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
816  } else {
817    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
818  }
819  owl_fmtext_append_normal(fm, "Default:        ");
820  owl_fmtext_append_normal(fm, buff);
821  owl_fmtext_append_normal(fm, "\n\n");
822
823  owl_fmtext_append_normal(fm, "Valid Settings: ");
824  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
825  owl_fmtext_append_normal(fm, "\n\n");
826
827  if (v->description && *v->description) {
828    owl_fmtext_append_normal(fm, "Description:\n");
829    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
830    owl_fmtext_append_normal(fm, "\n\n");
831  }
832}
833
834
835
836
837/**************************************************************************/
838/*********************** GENERAL TYPE-SPECIFIC ****************************/
839/**************************************************************************/
840
841/* default common functions */
842
843void *owl_variable_get_default(owl_variable *v) {
844  return v->val;
845}
846
847void owl_variable_free_default(owl_variable *v) {
848  if (v->val) owl_free(v->val);
849}
850
851/* default functions for booleans */
852
853int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
854  if (newval == NULL) return(0);
855  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
856  else return (0);
857}
858
859int owl_variable_bool_set_default(owl_variable *v, void *newval) {
860  if (v->validate_fn) {
861    if (!v->validate_fn(v, newval)) return(-1);
862  }
863  *(int*)v->val = *(int*)newval;
864  return(0);
865}
866
867int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
868  int i;
869  if (!strcmp(newval, "on")) i=1;
870  else if (!strcmp(newval, "off")) i=0;
871  else return(-1);
872  return (v->set_fn(v, &i));
873}
874
875int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
876  if (val == NULL) {
877    snprintf(buf, bufsize, "<null>");
878    return -1;
879  } else if (*(int*)val == 0) {
880    snprintf(buf, bufsize, "off");
881    return 0;
882  } else if (*(int*)val == 1) {
883    snprintf(buf, bufsize, "on");
884    return 0;
885  } else {
886    snprintf(buf, bufsize, "<invalid>");
887    return -1;
888  }
889}
890
891/* default functions for integers */
892
893int owl_variable_int_validate_default(owl_variable *v, void *newval) {
894  if (newval == NULL) return(0);
895  else return (1);
896}
897
898int owl_variable_int_set_default(owl_variable *v, void *newval) {
899  if (v->validate_fn) {
900    if (!v->validate_fn(v, newval)) return(-1);
901  }
902  *(int*)v->val = *(int*)newval;
903  return(0);
904}
905
906int owl_variable_int_set_fromstring_default(owl_variable *v, char *newval) {
907  int i;
908  char *ep = "x";
909  i = strtol(newval, &ep, 10);
910  if (*ep || ep==newval) return(-1);
911  return (v->set_fn(v, &i));
912}
913
914int owl_variable_int_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
915  if (val == NULL) {
916    snprintf(buf, bufsize, "<null>");
917    return -1;
918  } else {
919    snprintf(buf, bufsize, "%d", *(int*)val);
920    return 0;
921  } 
922}
923
924/* default functions for enums (a variant of integers) */
925
926int owl_variable_enum_validate(owl_variable *v, void *newval) { 
927  char **enums;
928  int nenums, val;
929  if (newval == NULL) return(0);
930  enums = atokenize(v->validsettings, ",", &nenums);
931  if (enums == NULL) return(0);
932  atokenize_free(enums, nenums);
933  val = *(int*)newval;
934  if (val < 0 || val >= nenums) {
935    return(0);
936  }
937  return(1);
938}
939
940int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
941  char **enums;
942  int nenums, i, val=-1;
943  if (newval == NULL) return(-1);
944  enums = atokenize(v->validsettings, ",", &nenums);
945  if (enums == NULL) return(-1);
946  for (i=0; i<nenums; i++) {
947    if (0==strcmp(newval, enums[i])) {
948      val = i;
949    }
950  }
951  atokenize_free(enums, nenums);
952  if (val == -1) return(-1);
953  return (v->set_fn(v, &val));
954}
955
956int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
957  char **enums;
958  int nenums, i;
959
960  if (val == NULL) {
961    snprintf(buf, bufsize, "<null>");
962    return -1;
963  }
964  enums = atokenize(v->validsettings, ",", &nenums);
965  i = *(int*)val;
966  if (i<0 || i>=nenums) {
967    snprintf(buf, bufsize, "<invalid:%d>",i);
968    atokenize_free(enums, nenums);
969    return(-1);
970  }
971  snprintf(buf, bufsize, "%s", enums[i]);
972  return 0;
973}
974
975/* default functions for stringeans */
976
977int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
978  if (newval == NULL) return(0);
979  else return (1);
980}
981
982int owl_variable_string_set_default(owl_variable *v, void *newval) {
983  if (v->validate_fn) {
984    if (!v->validate_fn(v, newval)) return(-1);
985  }
986  if (v->val) owl_free(v->val);
987  v->val = owl_strdup(newval);
988  return(0);
989}
990
991int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
992  return (v->set_fn(v, newval));
993}
994
995int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
996  if (val == NULL) {
997    snprintf(buf, bufsize, "<null>");
998    return -1;
999  } else {
1000    snprintf(buf, bufsize, "%s", (char*)val);
1001    return 0;
1002  }
1003}
1004
1005
1006
1007/**************************************************************************/
1008/************************* REGRESSION TESTS *******************************/
1009/**************************************************************************/
1010
1011#ifdef OWL_INCLUDE_REG_TESTS
1012
1013#include "test.h"
1014
1015int owl_variable_regtest(void) {
1016  owl_vardict vd;
1017  int numfailed=0;
1018  char buf[1024];
1019  owl_variable * v;
1020
1021  in_regtest = 1;
1022
1023  printf("# BEGIN testing owl_variable\n");
1024  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
1025
1026  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"rxping"));
1027  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
1028  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"rxping", buf, 1024));
1029  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
1030  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"rxping"));
1031  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"rxping"));
1032  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"rxping","off",0,0));
1033  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"rxping"));
1034  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"rxping","xxx",0,0));
1035  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"rxping"));
1036
1037
1038  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
1039  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
1040  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
1041
1042  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
1043  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
1044  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
1045  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
1046  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
1047  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
1048  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
1049  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
1050  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
1051  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
1052  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
1053  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
1054  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
1055
1056  owl_variable_dict_newvar_string(&vd, "stringvar", "", "", "testval");
1057  FAIL_UNLESS("get new string var", NULL != (v = owl_variable_get(&vd, "stringvar", OWL_VARIABLE_STRING)));
1058  FAIL_UNLESS("get new string val", !strcmp("testval", owl_variable_get_string(&vd, "stringvar")));
1059  owl_variable_set_string(&vd, "stringvar", "new val");
1060  FAIL_UNLESS("update string val", !strcmp("new val", owl_variable_get_string(&vd, "stringvar")));
1061
1062  owl_variable_dict_newvar_int(&vd, "intvar", "", "", 47);
1063  FAIL_UNLESS("get new int var", NULL != (v = owl_variable_get(&vd, "intvar", OWL_VARIABLE_INT)));
1064  FAIL_UNLESS("get new int val", 47 == owl_variable_get_int(&vd, "intvar"));
1065  owl_variable_set_int(&vd, "intvar", 17);
1066  FAIL_UNLESS("update bool val", 17 == owl_variable_get_int(&vd, "intvar"));
1067
1068  owl_variable_dict_newvar_bool(&vd, "boolvar", "", "", 1);
1069  FAIL_UNLESS("get new bool var", NULL != (v = owl_variable_get(&vd, "boolvar", OWL_VARIABLE_BOOL)));
1070  FAIL_UNLESS("get new bool val", owl_variable_get_bool(&vd, "boolvar"));
1071  owl_variable_set_bool_off(&vd, "boolvar");
1072  FAIL_UNLESS("update string val", !owl_variable_get_bool(&vd, "boolvar"));
1073
1074  owl_variable_dict_free(&vd);
1075
1076  /* if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n"); */
1077  printf("# END testing owl_variable (%d failures)\n", numfailed);
1078  return(numfailed);
1079}
1080
1081
1082#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.