# NAME

libslack(prog) - program framework module

# SYNOPSIS

        #include <slack/std.h>
        #include <slack/prog.h>

        typedef struct option option;
        typedef struct Option Option;
        typedef struct Options Options;

        typedef void opt_action_int_t(int arg);
        typedef void opt_action_optional_int_t(int *arg);
        typedef void opt_action_string_t(const char *arg);
        typedef void opt_action_optional_string_t(const char *arg);
        typedef void opt_action_none_t(void);
        typedef void func_t(void);

        enum OptionArgument
        {
            OPT_NONE,
            OPT_INTEGER,
            OPT_STRING
        };

        enum OptionAction
        {
            OPT_NOTHING,
            OPT_VARIABLE,
            OPT_FUNCTION
        };

        typedef enum OptionArgument OptionArgument;
        typedef enum OptionAction OptionAction;

        struct Option
        {
            const char *name;
            char short_name;
            const char *argname;
            const char *desc;
            int has_arg;
            OptionArgument arg_type;
            OptionAction action;
            void *object;
            func_t *function;
        };

        struct Options
        {
            Options *parent;
            Option *options;
        };

        void prog_init(void);
        const char *prog_set_name(const char *name);
        Options *prog_set_options(Options *options);
        const char *prog_set_syntax(const char *syntax);
        const char *prog_set_desc(const char *desc);
        const char *prog_set_version(const char *version);
        const char *prog_set_date(const char *date);
        const char *prog_set_author(const char *author);
        const char *prog_set_contact(const char *contact);
        const char *prog_set_vendor(const char *vendor);
        const char *prog_set_url(const char *url);
        const char *prog_set_legal(const char *legal);
        Msg *prog_set_out(Msg *out);
        Msg *prog_set_err(Msg *err);
        Msg *prog_set_dbg(Msg *dbg);
        Msg *prog_set_alert(Msg *alert);
        ssize_t prog_set_debug_level(size_t debug_level);
        ssize_t prog_set_verbosity_level(size_t verbosity_level);
        int prog_set_locker(Locker *locker);
        const char *prog_name(void);
        const Options *prog_options(void);
        const char *prog_syntax(void);
        const char *prog_desc(void);
        const char *prog_version(void);
        const char *prog_date(void);
        const char *prog_author(void);
        const char *prog_contact(void);
        const char *prog_vendor(void);
        const char *prog_url(void);
        const char *prog_legal(void);
        Msg *prog_out(void);
        Msg *prog_err(void);
        Msg *prog_dbg(void);
        Msg *prog_alert(void);
        size_t prog_debug_level(void);
        size_t prog_verbosity_level(void);
        int prog_out_fd(int fd);
        int prog_out_stdout(void);
        int prog_out_file(const char *path);
        int prog_out_syslog(const char *ident, int option, int facility, int priority);
        int prog_out_push_filter(msg_filter_t *filter);
        int prog_out_none(void);
        int prog_err_fd(int fd);
        int prog_err_stderr(void);
        int prog_err_file(const char *path);
        int prog_err_syslog(const char *ident, int option, int facility, int priority);
        int prog_err_push_filter(msg_filter_t *filter);
        int prog_err_none(void);
        int prog_dbg_fd(int fd);
        int prog_dbg_stdout(void);
        int prog_dbg_stderr(void);
        int prog_dbg_file(const char *path);
        int prog_dbg_syslog(const char *id, int option, int facility, int priority);
        int prog_dbg_push_filter(msg_filter_t *filter);
        int prog_dbg_none(void);
        int prog_alert_fd(int fd);
        int prog_alert_stdout(void);
        int prog_alert_stderr(void);
        int prog_alert_file(const char *path);
        int prog_alert_syslog(const char *id, int option, int facility, int priority);
        int prog_alert_push_filter(msg_filter_t *filter);
        int prog_alert_none(void);
        int prog_opt_process(int ac, char **av);
        void prog_usage_msg(const char *format, ...);
        void prog_help_msg(void);
        void prog_version_msg(void);
        const char *prog_basename(const char *path);
        extern Options prog_options_table[1];
        int opt_process(int argc, char **argv, Options *options, char *msgbuf, size_t bufsize);
        char *opt_usage(char *buf, size_t size, Options *options);

# DESCRIPTION

This module provides administrative services for arbitrary programs. The services include program identification; flexible, complete command line option processing; help, usage and version messages; flexible debug, verbose, error and normal messaging (simple call syntax with arbitrary message destinations including multiplexing).

This module exposes an alternate interface to GNU getopt_long(3). It defines a way to specify command line option syntax, semantics and descriptions in multiple, discrete chunks. The getopt functions require that the client specify the syntax and partial semantics for all options in the same place (if it is to be done statically). This can be annoying when library modules require their own command line options. This module allows various parts of a program to (statically) specify their own command line options independently, and link them together via `parent` pointers.

Option syntax is specified in much the same way as for GNU getopt_long(3). Option semantics are specified by an action (`OPT_NOTHING`, `OPT_VARIABLE` or `OPT_FUNCTION`), an argument type (`OPT_NONE`, `OPT_INTEGER` or `OPT_STRING`), and either an object (`int *`, `char **`) or function (`func()`, `func(int)` or `func(char *)`).

The opt_process(3) and opt_usage(3) functions are used by the prog functions and needn't be used directly. Instead, use prog_opt_process(3) to execute options and prog_usage_msg(3) and prog_help_msg(3) to construct usage and help messages directly from the supplied option data. They are exposed in case you don't want to use any other part of this module.

`void prog_init(void)`

  Initialises the message, error, debug, and alert destinations to `stdout`, `stderr`, `stderr`, and `stderr`, respectively. These are all `null` by default so this function must be called before any messages are emitted.

`const char *prog_set_name(const char *name)`

  Sets the program's name to `name`. This is used when composing usage, help, version, and error messages. On success, returns `name`. On error, returns `null` with `errno` set appropriately.

`Options *prog_set_options(Options *options)`

  Sets the program's options to `options`. This is used when processing the command line options with prog_opt_process(3). On success, returns `options`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_syntax(const char *syntax)`

  Sets the program's command line syntax summary to `syntax`. This is used when composing usage and help messages. It must contain a one line summary of the command line arguments, excluding the program name (e.g. `"[options] arg..."`). On success, returns `syntax`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_desc(const char *desc)`

  Sets the program's description to `desc`. This is used when composing help messages. On success, returns `desc`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_version(const char *version)`

  Sets the program's version string to `version`. This is used when composing help and version messages. On success, returns `version`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_date(const char *date)`

  Sets the program's release date to `date`. This is used when composing help messages. On success, returns `date`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_author(const char *author)`

  Sets the program's author to `author`. This is used when composing help messages. It must contain the (free format) name of the author. Returns `author`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_contact(const char *contact)`

  Sets the program's contact address to `contact`. This is used when composing help messages. It must contain the email address to which bug reports should be sent. On success, returns `contact`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_vendor(const char *vendor)`

  Sets the program's vendor to `vendor`. This is used when composing help messages. It must contain the (free format) name of the vendor. Returns `vendor`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_url(const char *url)`

  Sets the program's URL to `url`. This is used when composing help messages. It must contain the URL where the program can be downloaded. On success, returns `url`. On error, returns `null` with `errno` set appropriately.

`const char *prog_set_legal(const char *legal)`

  Sets the program's legal notice to `legal`. This is used when composing help messages. It is assumed that the legal notice may contain multiple lines and so must contain its own newline characters. On success, returns `legal`. On error, returns `null` with `errno` set appropriately.

`Msg *prog_set_out(Msg *out)`

  Sets the program's message destination to `out`. This is used by msg(3) and vmsg(3) which are, in turn, used to emit usage, version and help messages. The program message destination is set to standard output by prog_init(3), but it can be anything. However, it is probably best to leave it as standard output at least until after command line option processing is complete. See msg(3) for details. On success, returns `out`. On error, returns `null` with `errno` set appropriately.

`Msg *prog_set_err(Msg *err)`

  Sets the program's error message destination to `err`. This is used by error(3), errorsys(3), fatal(3), fatalsys(3), dump(3) and dumpsys(3). The program error message destination is set to standard error by prog_init(3), but it can be anything. See msg(3) for details. On success, returns `err`. On error, returns `null` with `errno` set appropriately.

`Msg *prog_set_dbg(Msg *dbg)`

  Sets the program's debug message destination to `dbg`. This is set to standard error by prog_init(3), but it can be set to anything. See msg(3) for details. On success, returns `dbg`. On error, returns `null` with `errno` set appropriately.

`Msg *prog_set_alert(Msg *alert)`

  Sets the program's alert message destination to `alert`. This is set to standard error by prog_init(3) but it can be set to anything. See msg(3) for details. On success, returns `alert`. On error, returns `null` with `errno` set appropriately.

`ssize_t prog_set_debug_level(size_t debug_level)`

  Sets the program's debug level to `debug_level`. This is used when determining whether or not to emit a debug message. The debug level comprises two parts, the section and the level. The level occupies the low byte of `debug_level`. The section occupies the next three bytes. This enables debugging to be partitioned into sections, allowing users to turn on debugging at any level (from 0 up to 255) for particular sections of a program (at most 24). Debug messages with a section value whose bits overlap those of the program's current debug section and with a level that is less than or equal to the program's current debug level are emitted. As a convenience, if the program debug section is zero, debug messages with a sufficiently small level are emitted regardless of the message section. On success, returns the previous debug level. On error, returns `-1` with `errno` set appropriately.

  Example:

          #define LEXER_SECTION  (1 << 8)
          #define PARSER_SECTION (2 << 8)
          #define INTERP_SECTION (4 << 8)

          prog_set_debug_level(LEXER_SECTION | PARSER_SECTION | 1);
          debug((LEXER_SECTION  | 1, "lexer debugmsg"))  // yes
          debug((LEXER_SECTION  | 4, "lexer debugmsg"))  // no (level too high)
          debug((PARSER_SECTION | 1, "parser debugmsg")) // yes
          debug((INTERP_SECTION | 1, "interp debugmsg")) // no (wrong section)
          debug((1, "global debug"))                  // no (no section to match)

          prog_set_debug_level(1);
          debug((LEXER_SECTION  | 1, "lexer debugmsg"))  // yes
          debug((LEXER_SECTION  | 4, "lexer debugmsg"))  // no (level too high)
          debug((PARSER_SECTION | 1, "parser debugmsg")) // yes
          debug((INTERP_SECTION | 1, "interp debugmsg")) // yes
          debug((1, "global debugmsg"))                  // yes
          debug((4, "global debugmsg"))                  // no (level too high)

`ssize_t prog_set_verbosity_level(size_t verbosity_level)`

  Sets the program's verbosity level to `verbosity_level`. This is used to determine whether or not to emit verbose messages. Verbose messages with a level that is less than or equal to the program's current verbosity level are emitted. On success, returns the previous verbosity level. On error, returns `-1` with `errno` set appropriately.

`int prog_set_locker(Locker *locker)`

  Sets the locker (multiple thread synchronisation strategy) for this module. This is only needed in multi-threaded programs. See locker(3) for details. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`const char *prog_name(void)`

  Returns the program's name as set by prog_set_name(3). On error, returns `null` with `errno` set appropriately.

`const Options *prog_options(void)`

  Returns the program's options as set by prog_set_options(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_syntax(void)`

  Returns the program's command line syntax summary as set by prog_set_syntax(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_desc(void)`

  Returns the program's description as set by prog_set_desc(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_version(void)`

  Returns the program's version string as set by prog_set_version(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_date(void)`

  Returns the program's release date as set by prog_set_date(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_author(void)`

  Returns the program's author as set by prog_set_author(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_contact(void)`

  Returns the program's contact address as set by prog_set_contact(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_vendor(void)`

  Returns the program's vendor as set by prog_set_vendor(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_url(void)`

  Returns the program's URL as set by prog_set_url(3). On error, returns `null` with `errno` set appropriately.

`const char *prog_legal(void)`

  Returns the program's legal notice as set by prog_set_legal(3). On error, returns `null` with `errno` set appropriately.

`Msg *prog_out(void)`

  Returns the program's message destination as set by prog_set_out(3). On error, returns `null` with `errno` set appropriately.

`Msg *prog_err(void)`

  Returns the program's error message destination as set by prog_set_err(3). On error, returns `null` with `errno` set appropriately.

`Msg *prog_dbg(void)`

  Returns the program's debug message destination as set by prog_set_dbg(3). On error, returns `null` with `errno` set appropriately.

`Msg *prog_alert(void)`

  Returns the program's alert message destination as set by prog_set_alert(3). On error, returns `null` with `errno` set appropriately.

`size_t prog_debug_level(void)`

  Returns the program's debug level as set by prog_set_debug_level(3). On error, returns `0` with `errno` set appropriately.

`size_t prog_verbosity_level(void)`

  Returns the program's verbosity level as set by prog_set_verbosity_level(3). On error, returns `0` with `errno` set appropriately.

`int prog_out_fd(int fd)`

  Sets the program's normal message destination to be the file descriptor, `fd`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_out_stdout(void)`

  Sets the program's normal message destination to be standard output. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_out_file(const char *path)`

  Sets the program's normal message destination to be the file specified by `path`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_out_syslog(const char *ident, int option, int facility, int priority)`

  Sets the program's normal message destination to be syslog initialised with `ident`, `option`, `facility`, and `priority`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_out_push_filter(msg_filter_t *filter)`

  Pushes the message filter function, filter, onto the program's normal message destination. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_out_none(void)`

  Sets the program's normal message destination to `null`. This disables all normal messages. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_err_fd(int fd)`

  Sets the program's error message destination to be the file descriptor, `fd`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_err_stderr(void)`

  Sets the program's error message destination to be standard error. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_err_file(const char *path)`

  Sets the program's error message destination to be the file specified by `path`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_err_syslog(const char *ident, int option, int facility, int priority)`

  Sets the program's error message destination to be syslog initialised with `ident`, `option`, `facility`, and `priority`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_err_push_filter(msg_filter_t *filter)`

  Pushes the message filter function, filter, onto the program's error message destination. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_err_none(void)`

  Sets the program's error message destination to `null`. This disables all error messages. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_fd(int fd)`

  Sets the program's debug message destination to be the file descriptor, `fd`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_stdout(void)`

  Sets the program's debug message destination to be standard output. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_stderr(void)`

  Sets the program's debug message destination to be standard error. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_file(const char *path)`

  Sets the program's debug message destination to be the file specified by `path`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_syslog(const char *id, int option, int facility, int priority)`

  Sets the program's debug message destination to be syslog initialised with `ident`, `option`, `facility`, and `priority`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_push_filter(msg_filter_t *filter)`

  Pushes the message filter function, filter, onto the program's debug message destination. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_dbg_none(void)`

  Sets the program's debug message destination to `null`. This disables all debug messages. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_fd(int fd)`

  Sets the program's alert message destination to be the file descriptor specified by `fd`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_stdout(void)`

  Sets the program's alert message destination to be standard output. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_stderr(void)`

  Sets the program's alert message destination to be standard error. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_file(const char *path)`

  Sets the program's alert message destination to be the file specified by `path`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_syslog(const char *id, int option, int facility, int priority)`

  Sets the program's alert message destination to be syslog initialised with `ident`, `option`, `facility`, and `priority`. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_push_filter(msg_filter_t *filter)`

  Pushes the message filter function, filter, onto the program's alert message destination. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_alert_none(void)`

  Sets the program's alert message destination to `null`. This disables all alert messages. On success, returns `0`. On error, returns `-1` with `errno` set appropriately.

`int prog_opt_process(int ac, char **av)`

  Parses and processes the command line options in `av`. If there is an error, a usage message is emitted and the program terminates. This function is just an interface to GNU getopt_long(3) that provides easier, more flexible, and more complete option handling. As well as supplying the syntax for options, this function requires their semantics and descriptions. The descriptions allow usage and help messages to be automatically composed by prog_usage_msg(3) and prog_help_msg(3). The semantics (which may be either a variable assignment or a function invocation) allow complete command line option processing to be performed with a single call to this function. On success, returns `optind`. On error (i.e. invalid option or option argument), calls prog_usage_msg(3) which terminates the program with a return code of `EXIT_FAILURE`. See the EXAMPLE section for details on specifying option data. See opt_process(3) for details on the processing of each option. On error, returns `-1` with `errno` set appropriately.

`void prog_usage_msg(const char *format, ...)`

  Emits a program usage error message, then terminates the program with a return code of `EXIT_FAILURE`. The usage message consists of the program's name, command line syntax, options and their descriptions (if they have been supplied), and the given message. `format` is a printf(3)-like format string. Any remaining arguments are processed as in printf(3).

  Warning: Do not under any circumstances ever pass a non-literal string as the format argument unless you know exactly how many conversions will take place. Being careless with this is a very good way to build potential security vulnerabilities into your programs. The same is true for all functions that take a printf()-like format string as an argument.

          prog_usage_msg(buf);       // EVIL
          prog_usage_msg("%s", buf); // GOOD

`void prog_help_msg(void)`

  Emits a program help message, then terminates the program with a return code of `EXIT_SUCCESS`. This message consists of the program's usage message, description, name, version, release date, author, vendor, URL, legal notice and contact address (if they have been supplied).

`void prog_version_msg(void)`

  Emits a program version message, then terminates the program with a return code of `EXIT_SUCCESS`. This message consists of the program's name and version (if they have been supplied).

`const char *prog_basename(const char *path)`

  Returns the filename part of `path`. On error, returns `null` with `errno` set appropriately.

`extern Options prog_options_table[1]`

  Contains the syntax, semantics and descriptions of some options that are available to all programs that use libslack. These options are:

  `-h`, `--help`

    Print a help message then exit

  `-V`, `--version`

    Print a version message then exit

  `-v`[level], `--verbose`[=level]

    Set the verbosity level (Defaults to 1 if level is not supplied)

  `-d`[level], `--debug`[=level]

    Set the debugging level (Defaults to 1 if level is not supplied)

  If your program supports no other options than these, `prog_options_table` can be passed directly to prog_set_options(3). Otherwise, `prog_options_table` should be assigned to the `parent` field of the `Options` structure that will be passed to prog_set_options(3).

`int opt_process(int argc, char **argv, Options *options, char *msgbuf, size_t bufsize)`

  Parses `argv` for options specified in `options`. Uses GNU getopt_long(3). As each option is encountered, its corresponding action is performed. On success, returns `optind`. On error, returns `-1` with `errno` set appropriately.

  The following table shows the actions that are applied to an option's `object` or `function` based on its `has_arg`, `arg_type` and `arg_action` attributes and whether or not an argument is present.

       has_arg           arg_type    arg_action   optarg action
       ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~ ~~~~~~
       required_argument OPT_INTEGER OPT_VARIABLE yes    *object = strtol(argument)
       required_argument OPT_STRING  OPT_VARIABLE yes    *object = argument
       required_argument OPT_INTEGER OPT_FUNCTION yes    function(strtol(argument))
       required_argument OPT_STRING  OPT_FUNCTION yes    function(argument)

       optional_argument OPT_INTEGER OPT_VARIABLE yes    *object = strtol(argument)
       optional_argument OPT_STRING  OPT_VARIABLE yes    *object = argument
       optional_argument OPT_INTEGER OPT_FUNCTION yes    function(&strtol(argument))
       optional_argument OPT_STRING  OPT_FUNCTION yes    function(argument)

       optional_argument OPT_INTEGER OPT_VARIABLE no     ++*object
       optional_argument OPT_STRING  OPT_VARIABLE no     nothing
       optional_argument OPT_INTEGER OPT_FUNCTION no     function(NULL)
       optional_argument OPT_STRING  OPT_FUNCTION no     function(NULL)

       no_argument       OPT_NONE    OPT_VARIABLE no     ++*object
       no_argument       OPT_NONE    OPT_FUNCTION no     function()

  Note that integer option arguments may be expressed in octal, decimal or hexadecimal. There may be leading whitespace but no trailing text of any kind. Overflow and underflow are also treated as errors.

`char *opt_usage(char *buf, size_t size, Options *options)`

  Writes a usage message into `buf` that displays the names, syntax and descriptions of all options in `options`. `options` is traversed depth first so the chunk with the `null` `parent` appears first. Each chunk of options is preceded by a blank line. No more than `size` bytes are written, including the terminating `nul` character. The string returned will look like:

            -a, --aaa       -- no-arg/var option
            -b, --bbb       -- no-arg/func option
            -c, --ccc=arg   -- int-arg/var option
            -d, --ddd=arg   -- int-arg/func option
            -e, --eee=arg   -- str-arg/var option
            -f, --fff=arg   -- str-arg/func option
            -g, --ggg[=arg] -- opt-int-arg/var option
            -h, --hhh[=arg] -- opt-str-arg/func option with one of those really,
                               really, really, long descriptions that goes on and on
                               and even contains a really long url:
                               http://www.zip.com.au/~joe/fairly/long/url/index.html
                               would you believe? Here it is again!
                               http://www.zip.com.au/~joe/fairly/long/url/index.html#just_kidding

# ERRORS

On error, `errno` is set either by an underlying function, or as follows:

`EINVAL`

  Arguments are `null` or invalid.

`EDOM`

  An integer option argument string failed to be parsed completely.

`ERANGE`

  An integer option argument string was out of integer range. In this case, `INT_MAX` or `INT_MIN` is used.

# MT-Level

MT-Disciplined - prog functions

By default, this module is not threadsafe, because most programs are single-threaded, and synchronisation doesn't come for free. For multi-threaded programs, use prog_set_locker(3) to synchronise access to this module's data, before creating the threads that will access it.

Unsafe - opt functions

opt_process(3) and opt_usage(3) must only be used in the main thread. They should not be needed anywhere else. Normally, they would not be called directly at all.

# EXAMPLE

The following program:

     #include <slack/std.h>
     #include <slack/prog.h>

     char *name = NULL;
     int minimum = 0;
     int reverse = 0;

     void setup_syslog(char *facility) {}
     void parse_config(char *path) {}

     Option example_optab[] =
     {
         {
             "name", 'n', "name", "Provide a name",
             required_argument, OPT_STRING, OPT_VARIABLE, &name, NULL
         },
         {
             "minimum", 'm', "minval", "Ignore everything below minimum",
             required_argument, OPT_INTEGER, OPT_VARIABLE, &minimum, NULL
         },
         {
             "syslog", 's', "facility.priority", "Send client's output to syslog (defaults to local0.debug)",
             optional_argument, OPT_STRING, OPT_FUNCTION, NULL, (func_t *)setup_syslog
         },
         {
             "reverse", 'r', NULL, "Reverse direction",
             no_argument, OPT_NONE, OPT_VARIABLE, &reverse, NULL
         },
         {
             "config", 'c', "path", "Specify the configuration file",
             required_argument, OPT_STRING, OPT_FUNCTION, NULL, (func_t *)parse_config
         },
         {
             NULL, '\0', NULL, NULL, 0, 0, 0, NULL
         }
     };

     Options options[1] = {{ prog_options_table, example_optab }};

     int main(int ac, char **av)
     {
         int a;
         prog_init();
         prog_set_name("example");
         prog_set_syntax("[options] arg...");
         prog_set_options(options);
         prog_set_version("1.0");
         prog_set_date("20210220");
         prog_set_author("raf <raf@raf.org>");
         prog_set_contact(prog_author());
         prog_set_url("http://libslack.org/");
         prog_set_legal("This software is released under the terms of the GPL.\n");
         prog_set_desc("This program is an example of the prog module.\n");

         for (a = prog_opt_process(ac, av); a < ac; ++a)
             msg("av[%d] = \"%s\"\n", a, av[a]);

         return EXIT_SUCCESS;
     }

will behave like:

     $ example --version # to stdout
     example-1.0

     $ example --help # to stdout
     usage: example [options] arg...
     options:

           -h, --help                       - Print a help message then exit
           -V, --version                    - Print a version message then exit
           -v, --verbose[=level]            - Set the verbosity level
           -d, --debug[=level]              - Set the debugging level

           -n, --name=name                  - Provide a name
           -m, --minimum=minval             - Ignore everything below minimum
           -s, --syslog[=facility.priority] - Send client's output to syslog
                                              (defaults to local0.debug)
           -r, --reverse                    - Reverse direction
           -c, --config=path                - Specify the configuration file

     This program is an example of the prog module.

     Name: example
     Version: 1.0
     Date: 20210220
     Author: raf <raf@raf.org>
     URL: http://libslack.org/

     This software is released under the terms of the GPL.

     Report bugs to raf <raf@raf.org>

     $ example -x # to stderr
     ./example: invalid option -- x
     usage: example [options] arg...
     options:

           -h, --help                       - Print a help message then exit
           -V, --version                    - Print a version message then exit
           -v, --verbose[=level]            - Set the verbosity level
           -d, --debug[=level]              - Set the debugging level

           -n, --name=name                  - Provide a name
           -m, --minimum=minval             - Ignore everything below minimum
           -s, --syslog[=facility.priority] - Send client's output to syslog
                                              (defaults to local0.debug)
           -r, --reverse                    - Reverse direction
           -c, --config=path                - Specify the configuration file

     $ example a b c # to stdout
     av[1] = "a"
     av[2] = "b"
     av[3] = "c"

# SEE ALSO

libslack(3), getopt_long(3), err(3), msg(3), prop(3), sig(3), locker(3)

# AUTHOR

20210220 raf <raf@raf.org>