BACK to addon.html#config_edit

[= AutoGen5 Template -*- Mode: C -*-

=][= # /*

DESCRIPTION:
Config file editor
Create a program to edit a daemon config file by processing the options,
rewriting the config file and sending SIGHUP to the daemon.

PURPOSE:
   This template will produce a program that will process its configuration
   file and command line options, save the option state to its config file,
   and then signal its associated daemon file with a SIGHUP.  Included with
   this template are some auxialiary options and attributes in a file named
   "editor.def".

YOU SUPPLY:
   an AutoGen definitions file.  It must contain the following:

   The definitions line:
      autogen definitions options;

   The name of the config file editor program.  e.g.:
      prog-name = edit-daemon-conf;

   Include directives for "editor.def" and your daemon's options.  e.g.:
      #include editor.def
      #include daemon-opts.def

THE TEMPLATE PRODUCES:

   After processing this definitions file with:
      autogen edit-daemon-conf.def

   you will have a header and .c file for a  program named edit-daemon-conf.
   compile this thus:

      cflags=$( autoopts-config cflags)
      ldflags=$(autoopts-config ldflags)
      cc -o edit-daemon-conf $cflags edit-daemon-conf.c $ldflags

   the result is a program with this usage text:

   edit-daemon-conf - example dynamic config daemon - Ver. 1.2
   USAGE:  edit-daemon-conf [ -<flag> [<val>] | --<name>[{=| }<val>] ]...
     Flg Arg Option-Name    Description
         Num pid            pid of daemon process
                                   - an alternate for pid-file
         Fil pid-file       file containing daemon pid
                                   - file must pre-exist
                                   - may not be preset
         no  no-sighup      do not send SIGHUP to daemon
                                   - an alternate for pid-file
   [[options from the daemon]]
      -R Str reset-option   Reset an option's state
      -? no  help           Display usage information and exit
      -! no  more-help      Extended usage information passed thru pager
      -> opt save-opts      Save the option state to a config file
      -< Str load-opts      Load options from a config file
                                   - disabled as --no-load-opts
                                   - may appear multiple times

   Options are specified by doubled hyphens and their name
   or by a single hyphen and the flag character.

   The following option preset mechanisms are supported:
    - reading file [[config file name]]

   Running this program will re-compute the option state, save it away
   in the configuration file and, optionally, signal the daemon with
   SIGHUP to reload its configuration.  (Using any of four methods.
   If none of the three option methods is specified, then the "pkill"
   program will be used.)

 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

=][=
   (if (not (exist? "homerc"))
       (error "editor.tpl requires 'homerc' attribute"))
\=]
#include <sys/types.h>
#include <sys/wait.h>

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif

#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif

int
main(int argc, char** argv)
{
    int res = EXIT_SUCCESS;
    {
        int ct = optionProcess(&[=(. pname)=]Options, argc, argv);
        argc -= ct;
        argv += ct;
    }

    switch (argc) {
    case 1:
        SET_OPT_SAVE_OPTS(*argv);

    case 0:
        optionSaveFile(&[=(. pname)=]Options);
        break;

    default:
        fprintf(stderr, "%s error: too many operands\n",
                [=(. pname)=]Options.pzProgName);
        [=(. pname)=]Options.pUsageProc(&[=(. pname)=]Options, EXIT_FAILURE);
        /* NOTREACHED */
    }

    /* still here?  The options are fine and we've stored the new version */
    switch (WHICH_IDX_PID_FILE) {
    case INDEX_OPT_PID:
        if (kill(OPT_VALUE_PID, SIGHUP) != 0) {
        bad_kill:
            res = EXIT_FAILURE;
            fprintf(stderr, "fs error %d (%s) sending SIGHUP to pid %d\n",
                    errno, strerror(errno), OPT_VALUE_PID);
        }
        break;

    case INDEX_OPT_PID_FILE:
    {
        char buf[256];
        pid_t kill_pid;
        fread(buf, 1, sizeof(buf), OPT_VALUE_PID_FILE);
        kill_pid = (pid_t)strtoul(buf, NULL, 0);
        if (kill(kill_pid, SIGHUP) != 0)
            goto bad_kill;
        fclose(OPT_VALUE_PID_FILE);
        break;
    }

    case INDEX_OPT_NO_SIGHUP:
        return (EXIT_SUCCESS);

    case NO_EQUIVALENT:
    {
        /*
         *  No pid selected, so use "pkill" program.
         */
        static char const cmd_fmt[] =
            "pkill -hup -u %d [= prog-name[1] =]";
        char z[sizeof(cmd_fmt) + 10];
        uid_t myid = geteuid();
        sprintf(z, cmd_fmt, myid);
        res = system(z);
        if (res < 0)
            goto bad_kill;
        if (res != 0) {
            res = WEXITSTATUS(res);
            fprintf(stderr, "pkill exited with status %d\n\t%s\n", res, z);
        }
    }
    }

    return res;
}