libslack(prop) - program properties file module
#include <slack/std.h> #include <slack/prop.h> const char *prop_get(const char *name); const char *prop_get_or(const char *name, const char *default_value); const char *prop_set(const char *name, const char *value); int prop_get_int(const char *name); int prop_get_int_or(const char *name, int default_value); int prop_set_int(const char *name, int value); double prop_get_double(const char *name); double prop_get_double_or(const char *name, double default_value); double prop_set_double(const char *name, double value); int prop_get_bool(const char *name); int prop_get_bool_or(const char *name, int default_value); int prop_set_bool(const char *name, int value); int prop_unset(const char *name); int prop_save(void); int prop_clear(void); int prop_locker(Locker *locker);
This module provides support for system-wide and user-specific (generic and program-specific) properties in "well-known" locations:
/etc/properties/app - system-wide, generic properties $HOME/.properties/app - user-defined, generic properties /etc/properties/app.progname - system-wide, program-specific properties $HOME/.properties/app.progname - user-defined, program-specific properties
When the client first requests, sets or unsets a property, all properties relevant to the current program are loaded from these files in the order given above. This order ensures that program-specific properties override generic properties and user-defined properties override system-wide properties. The client can change properties at runtime and save the current properties back to disk (to the user-defined, program-specific properties file).
Program names (as returned by prog_name(3)) are converted into file name
suffixes by replacing every occurrence of the file path separator ('/'
)
with a '-'
. Properties files consist of one property per line.
Each property is specified by its name, followed by '='
followed by its
value. The name must not have a '='
in it unless it is quoted with a
preceding '\'
. Special characters are expressed in C string literal
notation (e.g. \a\b\f\n\r\t\v\x1b
). Spaces immediately before and after
the '='
are stripped unless they are quoted with a preceding '\'
. The
properties files may also contain blank lines and comments ('#'
until the
end of the line).
Boolean property values can be expressed as 0
or 1
, true
or
false
, yes
or no
, on
or off
(case insensitive).
const char *prop_get(const char *name)
Returns the value of the property named name
. Returns null
if there is
no such property. On error, returns null
with errno
set appropriately.
const char *prop_get_or(const char *name, const char *default_value)
Returns the value of the property named name
. Returns default_value
on
error or if there is no such property.
const char *prop_set(const char *name, const char *value)
Sets the property named name
to a copy of value
. If prop_save(3) is
called after a call to this function, the new property will be saved to disk
and will be available the next time this program is executed. On success,
returns the copy of value
. On error, returns null
with errno
set
appropriately.
int prop_get_int(const char *name)
Returns the value of the property named name
as an integer. Returns 0
on error or if there is no such property or if it is not interpretable as a
decimal integer.
int prop_get_int_or(const char *name, int default_value)
Returns the value of the property named name
as an integer. Returns
default_value
on error or if there is no such property or if it is not
interpretable as a decimal integer.
int prop_set_int(const char *name, int value)
Sets the property named name
to value
. If prop_save(3) is called
after a call to this function, the new property will be saved to disk and
will be available the next time this program is executed. On success,
returns value
. On error, returns 0
.
double prop_get_double(const char *name)
Returns the value of the property named name
as a double. Returns 0.0
on error or if there is no such property or if it is not interpretable as a
floating point number.
double prop_get_double_or(const char *name, double default_value)
Returns the value of the property named name
as a double. Returns
default_value
on error or if there is no such property or if it is not
interpretable as a floating point number.
double prop_set_double(const char *name, double value)
Sets the property named name
to value
. If prop_save(3) is called
after a call to this function, the new property will be saved to disk and
will be available the next time this program is executed. On success,
returns value
. On error, returns 0.0
.
int prop_get_bool(const char *name)
Returns the value of the property named name
as a boolean value. Returns
0
on error or if there is no such property. The values: "true"
,
"yes"
, "on"
and "1"
are all interpreted as true
. All other
values are interpreted as false
.
int prop_get_bool_or(const char *name, int default_value)
Returns the value of the property named name
as a boolean value. Returns
default_value
on error or if there is no such property or if it is not
interpretable as a boolean value. The values: "true"
, "yes"
, "on"
and "1"
are all interpreted as true
. The values: "false"
, "no"
,
"off"
and "0"
are all interpreted as false
. All other values are
disregarded and will cause default_value
to be returned.
int prop_set_bool(const char *name, int value)
Sets the property named name
to value
. If prop_save(3) is called
after a call to this function, the new property will be saved to disk and
will be available the next time this program is executed. On success,
returns value
. On error, returns 0
.
int prop_unset(const char *name)
Removes the property named name
. Property removal is only saved to disk
when prop_save(3) is called, if the property existed only in the
user-defined, program-specific properties file, or was created by the
program at runtime. On success, returns 0
. On error, returns -1
with
errno
set appropriately.
int prop_save(void)
Saves the program's properties to disk. If the "save"
property is set to
"false"
, "no"
, "off"
or "0"
, nothing is written to disk. If no
properties were added, removed or changed, nothing is written to disk. Only
the user-defined, program-specific properties are saved. Generic and
system-wide properties files must be edited by hand. Each program can only
save its own properties. They are saved in the following file:
$HOME/.properties/app.progname
Where progname
is the name of the program after being translated as
described at the top of the DESCRIPTION section.
The .properties directory is created if necessary. On success, returns
0
. On error, returns -1
with errno
set appropriately.
int prop_clear(void)
Clears the properties as though they were never initialised. On success,
returns 0
. On error, returns -1
with errno
set appropriately.
int prop_locker(Locker *locker)
Sets the locking strategy for the prop(3) module to locker
. This is
only needed in multi threaded programs. It must only be called once, from
the main thread. On success, returns 0
. On error, returns -1
with
errno
set appropriately.
On error, errno
is set either by an underlying function, or as follows:
EINVAL
When there is no prog_name or home directory or when there is a parse error in a properties file or if the ~/.properties exists but is not a directory. prop_locker(3) sets this when an attempt is made to change the locker that has already been set.
MT-Disciplined
/etc/properties/app $HOME/.properties/app /etc/properties/app.* $HOME/.properties/app.*
#include <slack/std.h> #include <slack/prog.h> #include <slack/prop.h> #include <slack/err.h> int main(int ac, char **av) { const char *s; int i; double d; int b; prog_init(); prog_set_name(*av); s = prop_get("string"); i = prop_get_int_or("int", 1); d = prop_get_double_or("double", 1.0); b = prop_get_bool("boolean"); msg("s = '%s'\ni = %d\nd = %g\nb = %s\n", s, i, d, (b) ? "true" : "false"); prop_set("string", "strung"); prop_set_int("int", i += 4); prop_set_double("double", d *= 1.75); prop_set_bool("boolean", !b); prop_save(); return EXIT_SUCCESS; }
This only provides coarse-grained persistence. If multiple instances of the same program are setting properties, the last to exit wins. This can be overcome by calling prop_save() after setting any property and prop_clear() before getting any property.
libslack(3), prog(3)
20100612 raf <raf@raf.org>