+static char *get_config_file_name(void)
+{
+ char *home, *config_file;
+
+ if (OPT_GIVEN(DSS, CONFIG_FILE))
+ return dss_strdup(OPT_STRING_VAL(DSS, CONFIG_FILE));
+ home = get_homedir();
+ config_file = make_message("%s/.dssrc", home);
+ free(home);
+ return config_file;
+}
+
+static int send_signal(int sig, bool wait)
+{
+ pid_t pid;
+ char *config_file = get_config_file_name();
+ int ret = get_dss_pid(config_file, &pid);
+ unsigned ms = 32;
+ struct timespec ts;
+
+ free(config_file);
+ if (ret < 0)
+ return ret;
+ if (OPT_GIVEN(DSS, DRY_RUN)) {
+ dss_msg("%d\n", (int)pid);
+ return 0;
+ }
+ DSS_NOTICE_LOG(("sending signal %d to pid %d\n", sig, (int)pid));
+ ret = kill(pid, sig);
+ if (ret < 0)
+ return -ERRNO_TO_DSS_ERROR(errno);
+ if (!wait)
+ return 1;
+ while (ms < 5000) {
+ ts.tv_sec = ms / 1000;
+ ts.tv_nsec = (ms % 1000) * 1000 * 1000;
+ ret = nanosleep(&ts, NULL);
+ if (ret < 0)
+ return -ERRNO_TO_DSS_ERROR(errno);
+ ret = kill(pid, 0);
+ if (ret < 0) {
+ if (errno != ESRCH)
+ return -ERRNO_TO_DSS_ERROR(errno);
+ return 1;
+ }
+ ms *= 2;
+ }
+ return -E_KILL_TIMEOUT;
+}
+
+struct signal_info {
+ const char * const name;
+ int num;
+};
+
+/*
+ * The table below was taken 2016 from proc/sig.c of procps-3.2.8. Copyright
+ * 1998-2003 by Albert Cahalan, GPLv2.
+ */
+static const struct signal_info signal_table[] = {
+ {"ABRT", SIGABRT}, /* IOT */
+ {"ALRM", SIGALRM},
+ {"BUS", SIGBUS},
+ {"CHLD", SIGCHLD}, /* CLD */
+ {"CONT", SIGCONT},
+ {"FPE", SIGFPE},
+ {"HUP", SIGHUP},
+ {"ILL", SIGILL},
+ {"INT", SIGINT},
+ {"KILL", SIGKILL},
+ {"PIPE", SIGPIPE},
+#ifdef SIGPOLL
+ {"POLL", SIGPOLL}, /* IO */
+#endif
+ {"PROF", SIGPROF},
+#ifdef SIGPWR
+ {"PWR", SIGPWR},
+#endif
+ {"QUIT", SIGQUIT},
+ {"SEGV", SIGSEGV},
+#ifdef SIGSTKFLT
+ {"STKFLT", SIGSTKFLT},
+#endif
+ {"STOP", SIGSTOP},
+ {"SYS", SIGSYS}, /* UNUSED */
+ {"TERM", SIGTERM},
+ {"TRAP", SIGTRAP},
+ {"TSTP", SIGTSTP},
+ {"TTIN", SIGTTIN},
+ {"TTOU", SIGTTOU},
+ {"URG", SIGURG},
+ {"USR1", SIGUSR1},
+ {"USR2", SIGUSR2},
+ {"VTALRM", SIGVTALRM},
+ {"WINCH", SIGWINCH},
+ {"XCPU", SIGXCPU},
+ {"XFSZ", SIGXFSZ}
+};
+
+#define SIGNAL_TABLE_SIZE (sizeof(signal_table) / sizeof(signal_table[0]))
+#ifndef SIGRTMAX
+#define SIGRTMAX 64
+#endif
+
+static int com_kill(void)
+{
+ bool w_given = OPT_GIVEN(KILL, WAIT);
+ const char *arg = OPT_STRING_VAL(KILL, SIGNAL);
+ int ret, i;
+
+ if (*arg >= '0' && *arg <= '9') {
+ int64_t val;
+ ret = dss_atoi64(arg, &val);
+ if (ret < 0)
+ return ret;
+ if (val < 0 || val > SIGRTMAX)
+ return -ERRNO_TO_DSS_ERROR(EINVAL);
+ return send_signal(val, w_given);
+ }
+ if (strncasecmp(arg, "sig", 3) == 0)
+ arg += 3;
+ if (strcasecmp(arg, "CLD") == 0)
+ return send_signal(SIGCHLD, w_given);
+ if (strcasecmp(arg, "IOT") == 0)
+ return send_signal(SIGABRT, w_given);
+ for (i = 0; i < SIGNAL_TABLE_SIZE; i++)
+ if (strcasecmp(arg, signal_table[i].name) == 0)
+ return send_signal(signal_table[i].num, w_given);
+ DSS_ERROR_LOG(("invalid sigspec: %s\n", arg));
+ return -ERRNO_TO_DSS_ERROR(EINVAL);
+}
+EXPORT_CMD_HANDLER(kill);
+