tags 375433 patch
thanks
Hi,
Allied-Visions GmbH developed a patch to support custom commands (such as
reload) in sv's initscript emulation.
This required some changes in the way sv handles commands.
You can now have /service/foo/custom/reload, and sv reload foo will execute
that. This makes it possible to finally seamlessly support e.g. Debian
package upgrades where the original initscript has been replaced by a
symlink pointing to sv.
Best regards,
Andras
--
Andras Korn <korn at chardonnay.math.bme.hu>
<http://chardonnay.math.bme.hu/~korn/> QOTD:
cat dad*.dna mom*.dna >baby.out
Index: sv.c
===================================================================
--- sv.c (revision 144)
+++ sv.c (revision 146)
@@ -29,6 +29,9 @@
#define TIMEOUT "timeout: "
#define KILL "kill: "
+char custom_command_[64];
+char *custom_command = custom_command_+7;
+
char *progname;
char *action;
char *acts;
@@ -204,6 +207,43 @@
return(!wait_exitcode(w));
}
+int execute_custom_command()
+{
+ char *prog[2];
+ int pid, w;
+
+ if ((pid =fork()) == -1) {
+ outs2(WARN); outs2("unable to fork for "); outs2(*service);
+ outs2(custom_command); outs2(error_str(errno)); flush2("\n");
+ return(0);
+ }
+ if (!pid) {
+ /* Probably faster than a for cycle for 9 bytes) */
+ custom_command_[0] = 'c';
+ custom_command_[1] = 'u';
+ custom_command_[2] = 's';
+ custom_command_[3] = 't';
+ custom_command_[4] = 'o';
+ custom_command_[5] = 'm';
+ custom_command_[6] = '/';
+ prog[0] =custom_command_;
+ prog[1] =0;
+ close(1);
+ execve(custom_command_, prog, environ);
+ outs2(WARN); outs2("unable to run "); outs2(*service); outs2("/");outs2(custom_command_);outs2(": ");
+ outs2(error_str(errno)); flush2("\n");
+ _exit(0);
+ }
+ while (wait_pid(&w, pid) == -1) {
+ if (errno == error_intr) continue;
+ outs2(WARN); outs2("unable to wait for child "); outs2(*service);
+ outs2("/");outs2(custom_command_);outs2(": ");outs2(error_str(errno)); flush2("\n");
+ return(0);
+ }
+ return(!wait_exitcode(w));
+
+}
+
int check(char *a) {
unsigned int pid;
@@ -216,6 +256,9 @@
pid <<=8; pid +=(unsigned char)svstatus[12];
switch (*a) {
case 'x': return(0);
+ case '0':
+ execute_custom_command();
+ break;
case 'u':
if (!pid || svstatus[19] != 1) return(0);
if (!checkscript()) return(0);
@@ -261,9 +304,62 @@
return(1);
}
+typedef enum {
+ argf_kll = 1, /* Set kll to 1 */
+ argf_act0 = 2, /* Set act to 0 */
+ argf_acts = 4, /* Set act to &status */
+} arg_flag_t;
+
+typedef struct {
+ char *name;
+ char *acts;
+ void *cbk;
+ arg_flag_t flags;
+} arg_t ;
+
+/* Built in arguments - what is not listed here is taken as custom */
+arg_t arguments[] = {
+/* Argument acts cbk flags */
+ {"exit", "x", NULL, 0},
+ {"x", "x", NULL, 0},
+ {"Exit", "x", check, argf_kll},
+ {"X", "x", check, argf_kll},
+ {"D", "d", check, argf_kll},
+ {"T", "tc", check, argf_kll},
+ {"c", "C", check, argf_act0},
+ {"check", "C", check, argf_act0},
+ {"tc", "tc", NULL, 0},
+ {"tcu", "tcu", NULL, 0},
+ {"down", "d", NULL, 0},
+ {"once", "o", NULL, 0},
+ {"up", "u", NULL, 0},
+ {"pause", "p", NULL, 0},
+ {"cont", "c", NULL, 0},
+ {"hup", "h", NULL, 0},
+ {"alarm", "a", NULL, 0},
+ {"interrupt", "i", NULL, 0},
+ {"quit", "q", NULL, 0},
+ {"term", "t", NULL, 0},
+ {"kill", "k", NULL, 0},
+ {"1", "1", NULL, 0},
+ {"2", "2", NULL, 0},
+ {"shutdown", "x", check, 0},
+ {"start", "u", check, 0},
+ {"stop", "d", check, 0},
+ {"status", "s", NULL, argf_acts},
+ {"s", "s", check, argf_acts},
+ {"restart", "tcu", check, 0},
+ {"force-reload", "tc", check, argf_kll},
+ {"force-restart", "tcu", check, argf_kll},
+ {"force-shutdown", "x", check, argf_kll},
+ {"force-stop", "d", check, argf_kll},
+ {NULL, NULL, NULL, 0} /* terminator record */
+} ;
+
int main(int argc, char **argv) {
unsigned int i, done;
char *x;
+ arg_t *arg;
progname =*argv;
for (i =str_len(*argv); i; --i) if ((*argv)[i -1] == '/') break;
@@ -293,42 +389,34 @@
act =&control; acts ="s";
if (verbose) cbk =✓
- switch (*action) {
- case 'x': case 'e':
- acts ="x"; break;
- case 'X': case 'E':
- acts ="x"; kll =1; cbk =✓ break;
- case 'D':
- acts ="d"; kll =1; cbk =✓ break;
- case 'T':
- acts ="tc"; kll =1; cbk =✓ break;
- case 'c':
- if (!str_diff(action, "check")) { act =0; acts ="C"; cbk =✓ break; }
- case 'u': case 'd': case 'o': case 't': case 'p': case 'h':
- case 'a': case 'i': case 'k': case 'q': case '1': case '2':
- action[1] =0; acts =action; break;
- case 's':
- if (!str_diff(action, "shutdown")) { acts ="x"; cbk =✓ break; }
- if (!str_diff(action, "start")) { acts ="u"; cbk =✓ break; }
- if (!str_diff(action, "stop")) { acts ="d"; cbk =✓ break; }
- if (lsb && str_diff(action, "status")) usage();
- act =&status; cbk =0; break;
- case 'r':
- if (!str_diff(action, "restart")) { acts ="tcu"; cbk =✓ break; }
- usage();
- case 'f':
- if (!str_diff(action, "force-reload"))
- { acts ="tc"; kll =1; cbk =✓ break; }
- if (!str_diff(action, "force-restart"))
- { acts ="tcu"; kll =1; cbk =✓ break; }
- if (!str_diff(action, "force-shutdown"))
- { acts ="x"; kll =1; cbk =✓ break; }
- if (!str_diff(action, "force-stop"))
- { acts ="d"; kll =1; cbk =✓ break; }
- default:
- usage();
+
+ /* Compare action to all known attributes */
+ for(arg = arguments; arg->name != NULL; arg++) {
+ if (!(str_diff(arg->name, action))) {
+ acts = arg->acts;
+ cbk = arg->cbk;
+ if ((arg->flags & argf_kll) != 0)
+ kll = 1;
+ if ((arg->flags & argf_act0) != 0)
+ act = 0;
+ if ((arg->flags & argf_acts) != 0)
+ act = &status;
+ break;
+ }
}
+ /* If argument is not found in the table, it is custom */
+ if (arg->name == NULL) {
+ char *in, *out;
+ int len;
+ act =0;
+ acts ="0";
+ cbk =✓
+ for(in = action, out = custom_command, len=sizeof(custom_command_)-8; (*in != '\0') && (len > 0); in++, out++, len--)
+ *out = *in;
+ *out = '\0';
+ }
+
servicex =service;
for (i =0; i < services; ++i) {
if ((**service != '/') && (**service != '.')) {