~aperezdc/dmon

b85b4a570ae235032ba978aef209a0cebd492c4d — Adrian Perez de Castro 4 years ago 671671b
multicall: Support listing available applets

Add support for listing the available applets in a multicall dmon
binary, if the DMON_LIST_MULTICALL_APPLETS environment variable is
set. In that case only the list is printed, one item per line, and
the program will exit immediately.
3 files changed, 41 insertions(+), 24 deletions(-)

M CHANGELOG.md
M dmon.rst
M multicall.c
M CHANGELOG.md => CHANGELOG.md +4 -0
@@ 5,6 5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Support listing applets compiled into a multicall `dmon` binary when the
  `DMON_LIST_MULTICALL_APPLETS` environment variable is set and non-zero.

### Changed
- GNU Make is not required anymore, the included `Makefile` now works with
  the BSD variant as well, and probably others.

M dmon.rst => dmon.rst +4 -0
@@ 281,6 281,10 @@ variable, if defined. Any command line option can be specified this way.
Arguments read from the environment variable will be prepended to the ones
given in the command line, so they may still be overriden.

If the ``DMON_LIST_MULTICALL_APPLETS`` is defined and has a non-zero value,
the list of applets compiled into a multicall binary will be printed out,
and the program will exit immediately.


SEE ALSO
========

M multicall.c => multicall.c +33 -24
@@ 8,44 8,53 @@
#if defined(MULTICALL) && MULTICALL

#include "util.h"
#include <stdlib.h>
#include <string.h>

extern int dlog_main(int, char**);
extern int dmon_main(int, char**);
extern int drlog_main(int, char**);
extern int dslog_main(int, char**);

typedef int (*mainfunc_t)(int, char**);
#define APPLET_LIST_BEGIN   static mainfunc_t choose_applet (const char *name) {
#define APPLET(_n)          if (!strcmp (name, #_n)) return _n ## _main;
#define APPLET_LIST_END     return NULL; }


extern int dmon_main  (int, char**);
extern int dlog_main  (int, char**);
extern int dslog_main (int, char**);
extern int drlog_main (int, char**);


APPLET_LIST_BEGIN
    APPLET (dmon)
    APPLET (dlog)
    APPLET (dslog)
    APPLET (drlog)
APPLET_LIST_END
static const struct {
    const char *name;
    int (*func)(int, char**);
} applets[] = {
    { .name = "dmon", .func = dmon_main },
    { .name = "dlog", .func = dlog_main },
    { .name = "drlog", .func = drlog_main },
    { .name = "dslog", .func = dslog_main },
};


int
main (int argc, char **argv)
main(int argc, char **argv)
{
    const char *argv0 = strrchr (argv[0], '/');
    mainfunc_t mainfunc;

    const char *argv0 = strrchr(argv[0], '/');
    if (argv0 == NULL)
        argv0 = argv[0];
    else
        argv0++;

    mainfunc = choose_applet (argv0);
    const char *env = getenv("DMON_LIST_MULTICALL_APPLETS");
    const bool list = env && *env != '\0' && *env != '0';

    int (*mainfunc)(int, char**) = NULL;

    for (unsigned i = 0; i < sizeof(applets) / sizeof(applets[0]); i++) {
        if (list) {
            puts(applets[i].name);
        } else if (strcmp(argv0, applets[i].name) == 0) {
            mainfunc = applets[i].func;
            break;
        }
    }

    if (list)
        return EXIT_SUCCESS;

    if (mainfunc == NULL)
        die ("%s: No such applet in multicall binary.\n", argv0);
        die("%s: No such applet in multicall binary.\n", argv0);

    return (*mainfunc)(argc, argv);
}