Annotation of embedaddon/libpdel/config/app_config.3, revision 1.1

1.1     ! misho       1: .\" Copyright (c) 2001-2002 Packet Design, LLC.
        !             2: .\" All rights reserved.
        !             3: .\" 
        !             4: .\" Subject to the following obligations and disclaimer of warranty,
        !             5: .\" use and redistribution of this software, in source or object code
        !             6: .\" forms, with or without modifications are expressly permitted by
        !             7: .\" Packet Design; provided, however, that:
        !             8: .\" 
        !             9: .\"    (i)  Any and all reproductions of the source or object code
        !            10: .\"         must include the copyright notice above and the following
        !            11: .\"         disclaimer of warranties; and
        !            12: .\"    (ii) No rights are granted, in any manner or form, to use
        !            13: .\"         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            14: .\"         on advertising, endorsements, or otherwise except as such
        !            15: .\"         appears in the above copyright notice or in the software.
        !            16: .\" 
        !            17: .\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            18: .\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            19: .\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            20: .\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            21: .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            22: .\" OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            23: .\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            24: .\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            25: .\" RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            26: .\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            27: .\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            28: .\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            29: .\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            30: .\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            31: .\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            32: .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            33: .\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            34: .\" THE POSSIBILITY OF SUCH DAMAGE.
        !            35: .\"
        !            36: .\" Author: Archie Cobbs <archie@freebsd.org>
        !            37: .\"
        !            38: .\" $Id: app_config.3,v 1.12 2004/06/02 17:24:36 archie Exp $
        !            39: .\"
        !            40: .Dd April 22, 2002
        !            41: .Dt APP_CONFIG 3
        !            42: .Os
        !            43: .Sh NAME
        !            44: .Nm app_config
        !            45: .Nd application configuration system
        !            46: .Sh LIBRARY
        !            47: PDEL Library (libpdel, \-lpdel)
        !            48: .Sh SYNOPSIS
        !            49: .In sys/types.h
        !            50: .In pdel/config/app_config.h
        !            51: .Ft "struct app_config_ctx *"
        !            52: .Fn app_config_init "struct pevent_ctx *ctx" "const struct app_config *info" "void *cookie"
        !            53: .Ft int
        !            54: .Fn app_config_uninit "struct app_config_ctx **ctxp"
        !            55: .Ft "void *"
        !            56: .Fn app_config_get_cookie "struct app_config_ctx *ctx"
        !            57: .Ft int
        !            58: .Fn app_config_load "struct app_config_ctx *ctx" "const char *path" "int allow_writeback"
        !            59: .Ft int
        !            60: .Fn app_config_reload "struct app_config_ctx *ctx"
        !            61: .Ft "void *"
        !            62: .Fn app_config_new "struct app_config_ctx *ctx"
        !            63: .Ft int
        !            64: .Fn app_config_set "struct app_config_ctx *ctx" "const void *config" "u_long delay" "char *ebuf" "int emax"
        !            65: .Ft "void *"
        !            66: .Fn app_config_get "struct app_config_ctx *ctx" "int pending"
        !            67: .Ft "const struct structs_type *"
        !            68: .Fn app_config_get_type "struct app_config_ctx *ctx"
        !            69: .Ft "void *"
        !            70: .Fn app_config_copy "struct app_config_ctx *ctx" "const void *config"
        !            71: .Ft void
        !            72: .Fn app_config_free "struct app_config_ctx *ctx" "void **configp"
        !            73: .Vt extern const struct app_subsystem app_config_alog_subsystem ;
        !            74: .Vt extern const struct app_subsystem app_config_curconf_subsystem ;
        !            75: .Vt extern const struct app_subsystem app_config_directory_subsystem ;
        !            76: .Vt extern const struct app_subsystem app_config_pidfile_subsystem ;
        !            77: .Sh DESCRIPTION
        !            78: These functions implement an application configuration framework.
        !            79: .\"
        !            80: .Ss Application model
        !            81: .\"
        !            82: The
        !            83: .Nm app_config
        !            84: model assumes that the application's configuration is stored in a single
        !            85: .Em "configuration object" ,
        !            86: which can be any data structure that is describable by a
        !            87: .Xr structs 3
        !            88: type.
        !            89: The configuration can be stored in an XML file which is automatically updated.
        !            90: .Pp
        !            91: The application itself consists of one or more
        !            92: .Em subsystems .
        !            93: A subsystem is an abstract activity that can be started or stopped and
        !            94: whose behavior depends on (some part of) the configuration object.
        !            95: When the configuration object is changed, those subsystems that
        !            96: require it are automatically stopped and then restarted with the new
        !            97: configuration.
        !            98: .Pp
        !            99: The application may provide methods for:
        !           100: .Pp
        !           101: .Bl -bullet -compact -offset 3n
        !           102: .It
        !           103: Creating a new, default configuration object
        !           104: .It
        !           105: Initializing a new configuration object for the current system
        !           106: .It
        !           107: Checking a configuration object for overall validity
        !           108: .It
        !           109: Normalizing a configuration object
        !           110: .It
        !           111: Upgrading a configuration object from an old version
        !           112: .El
        !           113: .Pp
        !           114: Each subsystem may provide methods for:
        !           115: .Pp
        !           116: .Bl -bullet -compact -offset 3n
        !           117: .It
        !           118: Starting the subsystem
        !           119: .It
        !           120: Stopping the subsystem
        !           121: .It
        !           122: Determining if the subsystem will run
        !           123: .It
        !           124: Determining if the subsystem needs to be restarted
        !           125: .El
        !           126: .Pp
        !           127: In the steady state, there is a single currently active configuration object.
        !           128: Only those subsystems that are supposed to be running are.
        !           129: All running subsystems are running with their configurations based on
        !           130: (i.e., consistent with) the active configuration object.
        !           131: .Pp
        !           132: When there needs to be a configuration change, a new configuration object
        !           133: is constructed and the
        !           134: .Nm app_config
        !           135: library is told to apply the new configuration object.
        !           136: After a configurable delay (for hysteresis), those subsystems affected
        !           137: by the change are stopped, the new configuration object is installed
        !           138: in place of the old one, and the stopped subsystems are restarted.
        !           139: .Pp
        !           140: The
        !           141: .Nm app_config
        !           142: library guarantees that only "valid" configurations may be applied,
        !           143: where the meaning of "valid" is determined by the application.
        !           144: .\"
        !           145: .Ss Subsystems
        !           146: .\"
        !           147: A subsystem is defined as anything that can be started and/or stopped.
        !           148: A subsystem typically depends on some portion of the configuration
        !           149: object such that it must be stopped and restarted when that portion changes.
        !           150: .Pp
        !           151: A subsystem is defined by a
        !           152: .Li "struct app_subsystem" :
        !           153: .Pp
        !           154: .Bd -literal -compact -offset 3n
        !           155: struct app_subsystem {
        !           156:     const char          *name;      /* name, null to end list */
        !           157:     void                *arg;       /* opaque subsystem argument */
        !           158:     app_ss_startup_t    *start;     /* start subsystem */
        !           159:     app_ss_shutdown_t   *stop;      /* stop subsystem */
        !           160:     app_ss_willrun_t    *willrun;   /* will subsystem run? */
        !           161:     app_ss_changed_t    *changed;   /* subsystem config changed? */
        !           162:     const char          **deplist;  /* config items dependent on */
        !           163: };
        !           164: .Ed
        !           165: .Pp
        !           166: The
        !           167: .Fa name
        !           168: is currently used only for debugging, but must be
        !           169: .Dv NULL
        !           170: to terminate the list of subsystems (see below).
        !           171: The
        !           172: .Fa arg
        !           173: is ignored and is for the application's private use.
        !           174: The
        !           175: .Fa start ,
        !           176: .Fa stop ,
        !           177: .Fa willrun ,
        !           178: and
        !           179: .Fa changed
        !           180: fields must be pointers to functions having these types:
        !           181: .Pp
        !           182: .Bd -literal -compact -offset 3n
        !           183: typedef int  app_ss_startup_t(struct app_config_ctx *ctx,
        !           184:                 const struct app_subsystem *ss, const void *config);
        !           185: typedef void app_ss_shutdown_t(struct app_config_ctx *ctx,
        !           186:                 const struct app_subsystem *ss, const void *config);
        !           187: typedef int  app_ss_willrun_t(struct app_config_ctx *ctx,
        !           188:                 const struct app_subsystem *ss, const void *config);
        !           189: typedef int  app_ss_changed_t(struct app_config_ctx *ctx,
        !           190:                 const struct app_subsystem *ss,
        !           191:                 const void *config1, const void *config2);
        !           192: .Ed
        !           193: .Pp
        !           194: .Fn start
        !           195: starts the subsystem;
        !           196: .Fa config
        !           197: points to a copy of the current (i.e., new) configuration object.
        !           198: .Fn start
        !           199: should return zero if successful, or else -1 with
        !           200: .Va errno
        !           201: set on failure.
        !           202: In the latter case, the
        !           203: .Fn stop
        !           204: method will not be called.
        !           205: .Pp
        !           206: .Fn stop
        !           207: stops the subsystem;
        !           208: .Fa config
        !           209: points to a copy of the current configuration object.
        !           210: .Pp
        !           211: .Fn willrun
        !           212: should return non-zero if the subsystem needs to run at all.
        !           213: .Fa config
        !           214: points to a copy of the current (i.e., new) configuration object.
        !           215: .Pp
        !           216: .Fn changed
        !           217: determines if the subsystem needs to be restarted during a configuration
        !           218: change from
        !           219: .Fa config1
        !           220: to
        !           221: .Fa config2 .
        !           222: It should return 1 if so, zero otherwise.
        !           223: .Pp
        !           224: In the above methods, the configuration object argument(s)
        !           225: become invalid after the method returns.
        !           226: .Pp
        !           227: Alternately, or in conjunction with the
        !           228: .Fn changed
        !           229: method, the
        !           230: .Fa deplist
        !           231: may point to a
        !           232: .Dv NULL
        !           233: terminated list of
        !           234: .Xr structs 3
        !           235: names of fields in the configuration object on which this subsystem depends.
        !           236: The subsystem will automatically be restarted if any of the named fields
        !           237: differ between
        !           238: .Fa config1
        !           239: and
        !           240: .Fa config2 ,
        !           241: as determined by
        !           242: .Xr structs_equal 3 .
        !           243: .Pp
        !           244: All four of the above subsystem methods are optional and may be specified as
        !           245: .Dv NULL .
        !           246: In the case of
        !           247: .Fn startup
        !           248: and
        !           249: .Fn shutdown ,
        !           250: .Dv NULL
        !           251: means "do nothing".
        !           252: .Fn willrun
        !           253: being
        !           254: .Dv NULL
        !           255: is equivalent to it always returning 1.
        !           256: .Fn changed
        !           257: being
        !           258: .Dv NULL
        !           259: is equivalent to it always returning 0.
        !           260: .Fa deplist
        !           261: being
        !           262: .Dv NULL
        !           263: is equivalent to an empty list.
        !           264: .\"
        !           265: .Ss Application
        !           266: .\"
        !           267: An application itself is described by a
        !           268: .Li "struct app_config" :
        !           269: .Pp
        !           270: .Bd -literal -compact -offset 3n
        !           271: struct app_config {
        !           272:     u_int                       version;    /* current version # */
        !           273:     const struct structs_type   **types;    /* all version types */
        !           274:     const struct app_subsystem  **slist;    /* list of subsystems */
        !           275:     app_config_init_t           *init;      /* initialize defaults */
        !           276:     app_config_getnew_t         *getnew;    /* generate new config */
        !           277:     app_config_checker_t        *checker;   /* validate a config */
        !           278:     app_config_normalize_t      *normalize; /* normalize a config */
        !           279:     app_config_upgrade_t        *upgrade;   /* upgrade a config */
        !           280: };
        !           281: .Ed
        !           282: .Pp
        !           283: The list of subsystems supported by the application is pointed to by
        !           284: .Fa slist .
        !           285: This list must be terminated with an entry whose
        !           286: .Fa name
        !           287: is
        !           288: .Dv NULL .
        !           289: .Pp
        !           290: Subsystems are always started in the order they are listed in
        !           291: .Fa slist ,
        !           292: and they are always shutdown in the reverse order.
        !           293: .Pp
        !           294: The
        !           295: .Fa version
        !           296: is the configuration object version number (the first version is zero), and
        !           297: .Fa types
        !           298: points to an array of
        !           299: .Fa "version"
        !           300: + 1 pointers to
        !           301: .Xr structs 3
        !           302: types for the configuration object, where
        !           303: .Li "types[i]"
        !           304: is the
        !           305: .Xr structs 3
        !           306: type for version
        !           307: .Fa i
        !           308: of the configuration object.
        !           309: .Pp
        !           310: The remaining fields are pointers to functions having these types:
        !           311: .Pp
        !           312: .Bd -literal -compact -offset 3n
        !           313: typedef int  app_config_init_t(struct app_config_ctx *ctx,
        !           314:                  void *config);
        !           315: typedef int  app_config_getnew_t(struct app_config_ctx *ctx,
        !           316:                  void *config);
        !           317: typedef int  app_config_checker_t(struct app_config_ctx *ctx,
        !           318:                  const void *config, char *errbuf, size_t ebufsize);
        !           319: typedef void app_config_normalize_t(struct app_config_ctx *ctx,
        !           320:                  void *config);
        !           321: typedef int  app_config_upgrade_t(struct app_config_ctx *ctx,
        !           322:                  const void *old_conf, u_int old_version,
        !           323:                 void *new_conf);
        !           324: .Ed
        !           325: .Pp
        !           326: If the default configuration object is not equal to what is provided by
        !           327: .Xr structs_init 3 ,
        !           328: then
        !           329: .Fn init
        !           330: may be implemented.
        !           331: It should further modify the
        !           332: .Fa config
        !           333: as appropriate to get the generic default configuration.
        !           334: .Fn init
        !           335: returns zero on success, or -1 on error with
        !           336: .Va errno
        !           337: set appropriately.
        !           338: .Pp
        !           339: .Fn getnew
        !           340: is invoked when no existing configuration is found by
        !           341: .Fn app_config_load
        !           342: (see below).
        !           343: The
        !           344: .Fa config
        !           345: is as returned by
        !           346: .Fn init .
        !           347: .Fn getnew
        !           348: should apply any further initialization required for this particular system.
        !           349: .Fn getnew
        !           350: returns zero on success, or -1 on error with
        !           351: .Va errno
        !           352: set appropriately.
        !           353: .Pp
        !           354: The distinction between
        !           355: .Fn init
        !           356: and
        !           357: .Fn getnew
        !           358: is somewhat subtle:
        !           359: .Fn init
        !           360: simply initializes a new configuration object.
        !           361: It may be invoked many times during the normal operation of the application
        !           362: as configuration objects are needed.
        !           363: .Fn getnew
        !           364: is only invoked once, at the beginning of application startup, when there
        !           365: is no previously saved configuration found.
        !           366: Therefore, the behavior of
        !           367: .Fn init
        !           368: should not be affected by the "environment", while the behavior of
        !           369: .Fn getnew
        !           370: often is.
        !           371: .Pp
        !           372: .Fn checker
        !           373: determines whether the
        !           374: .Fa config
        !           375: is valid, returning 1 if so or 0 if not.
        !           376: In the latter case, it may print an error message (including '\\0')
        !           377: into the buffer
        !           378: .Fa errbuf ,
        !           379: which has size
        !           380: .Fa ebufsize
        !           381: (see
        !           382: .Xr snprintf 3) .
        !           383: .Pp
        !           384: .Fn normalize
        !           385: gives the application a chance to normalize an otherwise valid
        !           386: configuration object.
        !           387: This is useful when the configuration object contains redundant information,
        !           388: or information that can be represented in more than one way.
        !           389: .Pp
        !           390: All configurations that are applied by
        !           391: .Nm app_config
        !           392: are guaranteed to have been checked and normalized.
        !           393: All configurations passed to
        !           394: .Fn checker
        !           395: are guaranteed to have been passed through
        !           396: .Fn normalize
        !           397: first.
        !           398: .Pp
        !           399: Note: the configurations returned by
        !           400: .Fn init
        !           401: and
        !           402: .Fn getnew
        !           403: must be valid according to
        !           404: .Fa checker .
        !           405: .Pp
        !           406: .Fn upgrade
        !           407: is invoked when an older version of the configuration object is read
        !           408: in from an XML file.
        !           409: The configuration version number is stored as the "version" attribute
        !           410: of the XML document element.
        !           411: .Fa old_conf
        !           412: is the old object, which has version
        !           413: .Fa old_version ,
        !           414: and
        !           415: .Fa new_conf
        !           416: is a newly initialized configuration object of the current version.
        !           417: .Fn upgrade
        !           418: should copy the configuration information from
        !           419: .Fa old_conf
        !           420: to
        !           421: .Fa new_conf .
        !           422: .Pp
        !           423: A quick and dirty way to do this when most of the fields are the same
        !           424: is to use
        !           425: .Xr structs_traverse 3
        !           426: to list the fields in the old configuration object,
        !           427: .Xr structs_get_string 3
        !           428: to get their ASCII values, and
        !           429: .Xr structs_set_string 3
        !           430: to set the same values in the new configuration object.
        !           431: .\"
        !           432: .Ss API
        !           433: .\"
        !           434: .Fn app_config_init
        !           435: should be called at application startup time to initialize
        !           436: .Nm app_config
        !           437: for the application described by
        !           438: .Fa info .
        !           439: A
        !           440: .Xr pevent 3
        !           441: context
        !           442: .Fa ctx
        !           443: must be supplied.
        !           444: .Fn app_config_init
        !           445: returns an application context, with which all configuration and
        !           446: subsystems are associated.
        !           447: Multiple independent application contexts may exist at the same time.
        !           448: The
        !           449: .Fa cookie
        !           450: is saved along with the context but is otherwise ignored.
        !           451: .Pp
        !           452: .Fn app_config_uninit
        !           453: should be called at application shutdown time to release resources
        !           454: allocated by
        !           455: .Nm app_config .
        !           456: It may only be called when all subsystems are shutdown (i.e., the
        !           457: current configuration object pointer is
        !           458: .Dv NULL) .
        !           459: This enables
        !           460: .Fn app_config_init
        !           461: to be called again, if so desired.
        !           462: .Pp
        !           463: Upon return from
        !           464: .Fn app_config_uninit ,
        !           465: .Fa "*ctxp"
        !           466: will be set to
        !           467: .Dv NULL .
        !           468: If
        !           469: .Fa "*ctxp"
        !           470: is already equal to
        !           471: .Dv NULL
        !           472: when
        !           473: .Fn app_config_uninit
        !           474: is invoked, nothing happens.
        !           475: .Pp
        !           476: .Fn app_config_get_cookie
        !           477: retrieves the application cookie provided to
        !           478: .Fn app_config_init .
        !           479: .Pp
        !           480: .Fn app_config_load
        !           481: reads in an application configuration object from the XML file at
        !           482: .Fa path
        !           483: and applies it, making it the current configuration.
        !           484: If
        !           485: .Fa path
        !           486: is empty or non-existent, a new configuration object is created
        !           487: using the application's
        !           488: .Fn getnew
        !           489: method.
        !           490: .Pp
        !           491: If the file contains an old version of the configuration object,
        !           492: it is automatically upgraded to the current version.
        !           493: If
        !           494: .Fa allow_writeback
        !           495: is non-zero, then
        !           496: .Fa path
        !           497: is remembered and the file is updated (i.e., rewritten) every time
        !           498: the application configuration object changes.
        !           499: Updates are done atomically by creating a temporary file with the
        !           500: suffix ".new" and renaming it (see
        !           501: .Xr rename 2) .
        !           502: .Pp
        !           503: In theory, one call to
        !           504: .Fn app_config_load
        !           505: in an application's
        !           506: .Fn main
        !           507: routine is all that is required to get things going.
        !           508: .Pp
        !           509: .Fn app_config_reload
        !           510: reloads the configuration file previously specified to
        !           511: .Fn app_config_load
        !           512: and applies it.
        !           513: This would be the typical response to receiving a
        !           514: .Dv SIGHUP
        !           515: signal.
        !           516: .Pp
        !           517: .Fn app_config_new
        !           518: creates a new configuration object with the application's default values
        !           519: as specified by the application's
        !           520: .Fn init
        !           521: method.
        !           522: The returned pointer should be cast to the appropriate type.
        !           523: The caller is responsible for eventually freeing the returned
        !           524: configuration object by calling
        !           525: .Fn app_config_free .
        !           526: .Pp
        !           527: .Fn app_config_set
        !           528: changes the application's current configuration to be a copy of the
        !           529: configuration pointed to by
        !           530: .Fa config .
        !           531: If this configuration is invalid, -1 is returned with
        !           532: .Va errno
        !           533: set to
        !           534: .Er EINVAL ,
        !           535: and if
        !           536: .Fa ebuf
        !           537: is not
        !           538: .Dv NULL ,
        !           539: the buffer pointed to by
        !           540: .Fa ebuf
        !           541: and having size
        !           542: .Fa emax
        !           543: is filled in with a '\\0'-terminated error message.
        !           544: .Fn app_config_set
        !           545: may also return -1 with
        !           546: .Va errno
        !           547: set to other values in the case of system errors.
        !           548: .Pp
        !           549: If
        !           550: .Fa config
        !           551: is
        !           552: .Dv NULL ,
        !           553: all running subsystems will be shut down.
        !           554: Any configurations passed to
        !           555: .Fn app_config_set
        !           556: subsequent to passing a
        !           557: .Dv NULL
        !           558: configuration, but before the shutdown operation has completed, are ignored.
        !           559: This guarantees that a
        !           560: .Dv NULL
        !           561: configuration does actually shutdown the application.
        !           562: .Pp
        !           563: The new configuration (or shutdown) takes effect after a delay of
        !           564: .Fa delay
        !           565: milliseconds after
        !           566: .Fn app_config_set
        !           567: has successfully returned zero.
        !           568: The appropriate subsystem
        !           569: .Fn stop ,
        !           570: and then
        !           571: .Fn start
        !           572: methods are invoked serially from a new thread.
        !           573: .Pp
        !           574: .Fn app_config_get
        !           575: returns a copy of the current or pending configuration object.
        !           576: The returned pointer should be cast to the appropriate type.
        !           577: If
        !           578: .Fa pending
        !           579: is zero, then the configuration object currently in use is copied.
        !           580: Otherwise, the configuration object most recently applied via
        !           581: .Fn app_config_set
        !           582: is copied.
        !           583: These will be different when there is a pending, but not yet applied,
        !           584: configuration.
        !           585: The caller is responsible for eventually freeing the returned
        !           586: configuration object by calling
        !           587: .Fn app_config_free .
        !           588: .Pp
        !           589: .Fn app_config_get_type
        !           590: returns the
        !           591: .Xr structs 3
        !           592: for the application configuration object.
        !           593: .Pp
        !           594: .Fn app_config_copy
        !           595: copies a configuration object.
        !           596: The returned pointer should be cast to the appropriate type.
        !           597: The caller is responsible for eventually freeing the returned
        !           598: configuration object by calling
        !           599: .Fn app_config_free .
        !           600: .Pp
        !           601: .Fn app_config_free
        !           602: destroys the configuration object pointed to by
        !           603: .Fa "*configp" .
        !           604: Upon return,
        !           605: .Fa "*configp"
        !           606: will be set to
        !           607: .Dv NULL .
        !           608: If
        !           609: .Fa "*configp"
        !           610: is already
        !           611: .Dv NULL
        !           612: when
        !           613: .Fn app_config_free
        !           614: is invoked, nothing happens.
        !           615: .\"
        !           616: .Ss Pre-defined subsystems
        !           617: .\"
        !           618: The
        !           619: .Nm app_config
        !           620: library comes with some predefined subsystem templates.
        !           621: .Pp
        !           622: .Va app_config_alog_subsystem
        !           623: handles configuring error logging for an application.
        !           624: To use
        !           625: .Va app_config_alog_subsystem ,
        !           626: copy the structure and set the
        !           627: .Fa arg
        !           628: field to point to a
        !           629: .Li "struct app_config_alog_info" :
        !           630: .Pp
        !           631: .Bd -literal -compact -offset 3n
        !           632: struct app_config_alog_info {
        !           633:     const char  *name;      /* field name */
        !           634:     int         channel;    /* alog channel */
        !           635: };
        !           636: .Ed
        !           637: .Pp
        !           638: The
        !           639: .Fa name
        !           640: should be the
        !           641: .Xr structs 3
        !           642: field name of the field in the configuration object that configures
        !           643: logging for the
        !           644: .Xr alog 3
        !           645: logging channel
        !           646: .Fa channel .
        !           647: This field should be a
        !           648: .Li "struct alog_config" .
        !           649: .Pp
        !           650: .Va app_config_curconf_subsystem
        !           651: is useful when the application needs efficient access to the currently
        !           652: active configuration.
        !           653: This subsystem assumes that there is a global pointer variable (call it
        !           654: .Va curconf )
        !           655: which by definition always points to a read-only copy of the currently
        !           656: active configuration.
        !           657: For example, if the application's configuration object is a
        !           658: .Li "struct my_config" ,
        !           659: then
        !           660: .Va curconf
        !           661: would be defined as:
        !           662: .Pp
        !           663: .Bd -literal -compact -offset 3n
        !           664: const struct my_config *const curconf;
        !           665: .Ed
        !           666: .Pp
        !           667: Then the function of
        !           668: .Va app_config_curconf_subsystem
        !           669: is to automatically keep this variable up to date.
        !           670: (The
        !           671: .Li "const"
        !           672: keywords reflect the application's point of view:
        !           673: the first is because the structure is read-only, while the second
        !           674: is because the pointer itself is read-only.)
        !           675: .Pp
        !           676: To use
        !           677: .Va app_config_curconf_subsystem ,
        !           678: copy the structure and set the
        !           679: .Fa arg
        !           680: field to point to the application's
        !           681: .Va curconf
        !           682: pointer variable.
        !           683: Typically the
        !           684: .Va app_config_curconf_subsystem
        !           685: will be first in the list of subsystems, so that
        !           686: .Va curconf
        !           687: is always updated before any other subsystem starts.
        !           688: Then at any time
        !           689: .Va "*curconf"
        !           690: can be examined for the currently active configuration.
        !           691: .Pp
        !           692: .Va app_config_directory_subsystem
        !           693: handles configuring the current working directory for the process.
        !           694: To use
        !           695: .Va app_config_directory_subsystem ,
        !           696: copy the structure and set the
        !           697: .Fa arg
        !           698: field to point to a string containing the
        !           699: .Xr structs 3
        !           700: name of the field in the configuration object that contains the
        !           701: directory name.
        !           702: If this name is not the empty string, then the current working directory
        !           703: will be set according to the value of this field.
        !           704: .Pp
        !           705: .Va app_config_pidfile_subsystem
        !           706: handles "PID files", i.e., exclusive application lock files into which
        !           707: the process ID is written.
        !           708: These guard against two instances of the same application running at the
        !           709: same time.
        !           710: To use
        !           711: .Va app_config_pidfile_subsystem ,
        !           712: copy the structure and set the
        !           713: .Fa arg
        !           714: field to point to a string containing the
        !           715: .Xr structs 3
        !           716: name of the field in the configuration object that contains the PID file
        !           717: pathname.
        !           718: .Sh RETURN VALUES
        !           719: All of the
        !           720: .Nm app_config
        !           721: functions return
        !           722: .Dv NULL
        !           723: or -1 to indicate an error and set
        !           724: .Va errno
        !           725: appropriately.
        !           726: .Sh SEE ALSO
        !           727: .Xr alog 3 ,
        !           728: .Xr libpdel 3 ,
        !           729: .Xr pevent 3 ,
        !           730: .Xr structs 3 ,
        !           731: .Xr typed_mem 3
        !           732: .Sh HISTORY
        !           733: The PDEL library was developed at Packet Design, LLC.
        !           734: .Dv "http://www.packetdesign.com/"
        !           735: .Sh AUTHORS
        !           736: .An Archie Cobbs Aq archie@freebsd.org
        !           737: .Sh BUGS
        !           738: There should be explicit support for subsystems that require other
        !           739: subsystems to be running before they may run.
        !           740: As it stands now, such dependencies must be implicitly encoded into the
        !           741: .Fn willrun
        !           742: and
        !           743: .Fn changed
        !           744: methods.
        !           745: Even so, the dependent subsystem cannot detect if the other subsystem
        !           746: fails to start.
        !           747: .Pp
        !           748: Subsystems should be defined more like objects using dynamically
        !           749: allocated structures that can be added and removed from the subsystem
        !           750: list at any time, without having to shutdown and restart the whole
        !           751: application.
        !           752: .Pp
        !           753: It should be possible to start and shutdown subsystems individually.

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>