+/*---------------------------------------------------------
+ | execute_command
+ |
+ +--------------------------------------------------------- */
+
+static void on_sigchld(int signum, siginfo_t *info, void *uctx)
+{
+ if (info->si_pid == childpid) {
+ switch (info->si_code) {
+ case CLD_EXITED:
+ case CLD_KILLED:
+ case CLD_DUMPED:
+ childpid = 0;
+ killpg(info->si_pid, SIGKILL);
+ waitpid(info->si_pid, NULL, 0);
+ exit(0);
+ }
+ }
+}
+
+/*
+# @@ @
+# @p port
+# @t token
+*/
+
+#define SUBST_CHAR '@'
+#define SUBST_STR "@"
+
+static int instanciate_command_args()
+{
+ char *orig, *repl, *sub, *val, port[20];
+ int i, rc, r;
+ size_t s, l;
+
+ rc = snprintf(port, sizeof port, "%d", config->httpdPort);
+ if (rc < 0 || rc >= (int)(sizeof port))
+ return -1;
+
+ for (i = 0 ; (orig = config->exec[i]) ; i++) {
+ repl = 0;
+ s = 0;
+ for(;;) {
+ sub = strchrnul(orig, SUBST_CHAR);
+ l = sub - orig;
+ if (repl)
+ repl = mempcpy(repl, orig, l);
+ else
+ s += l;
+ if (!*sub) {
+ /* at end */
+ if (repl || orig == config->exec[i])
+ break;
+ repl = malloc(1 + s);
+ if (!repl)
+ return -1;
+ orig = config->exec[i];
+ config->exec[i] = repl;
+ repl[s] = 0;
+ } else {
+ r = 2;
+ switch(sub[1]) {
+ case 'p': val = port; break;
+ case 't': val = config->token ? : ""; break;
+ default: r = 1;
+ case SUBST_CHAR: val = SUBST_STR; break;
+ }
+ orig = &sub[r];
+ l = strlen(val);
+ if (repl)
+ repl = mempcpy(repl, val, l);
+ else
+ s += l;
+ }
+ }
+ }
+ return 0;
+}
+
+static int execute_command()
+{
+ struct sigaction siga;
+
+ /* check whether a command is to execute or not */
+ if (!config->exec || !config->exec[0])
+ return 0;
+
+ /* install signal handler */
+ memset(&siga, 0, sizeof siga);
+ siga.sa_sigaction = on_sigchld;
+ siga.sa_flags = SA_SIGINFO;
+ sigaction(SIGCHLD, &siga, NULL);
+
+ /* fork now */
+ childpid = fork();
+ if (childpid)
+ return 0;
+
+ /* makes arguments */
+ if (instanciate_command_args() >= 0) {
+ setpgid(0, 0);
+ execv(config->exec[0], config->exec);
+ ERROR("can't launch %s: %m", config->exec[0]);
+ }
+ exit(1);
+ return -1;
+}
+