source: variable.c @ dab82f29

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