--- /dev/null
+/* $Id$
+ Copyright 2007, Red Hat Inc. */
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <asm/unistd.h>
+#include <unistd.h>
+#define tkill(tid, sig) syscall (__NR_tkill, (tid), (sig))
+
+#define LENGTH(x) (sizeof (x) / sizeof (*(x)))
+
+struct signal
+ {
+ int signo;
+ const char *name;
+ };
+static const struct signal sigtab[] =
+ {
+#ifdef SIG0
+ { SIG0, "0" },
+#endif
+#ifdef SIGHUP
+ { SIGHUP, "HUP" },
+#endif
+#ifdef SIGINT
+ { SIGINT, "INT" },
+#endif
+#ifdef SIGQUIT
+ { SIGQUIT, "QUIT" },
+#endif
+#ifdef SIGILL
+ { SIGILL, "ILL" },
+#endif
+#ifdef SIGTRAP
+ { SIGTRAP, "TRAP" },
+#endif
+#ifdef SIGABRT
+ { SIGABRT, "ABRT" },
+#endif
+#ifdef SIGBUS
+ { SIGBUS, "BUS" },
+#endif
+#ifdef SIGFPE
+ { SIGFPE, "FPE" },
+#endif
+#ifdef SIGKILL
+ { SIGKILL, "KILL" },
+#endif
+#ifdef SIGUSR1
+ { SIGUSR1, "USR1" },
+#endif
+#ifdef SIGSEGV
+ { SIGSEGV, "SEGV" },
+#endif
+#ifdef SIGUSR2
+ { SIGUSR2, "USR2" },
+#endif
+#ifdef SIGPIPE
+ { SIGPIPE, "PIPE" },
+#endif
+#ifdef SIGALRM
+ { SIGALRM, "ALRM" },
+#endif
+#ifdef SIGTERM
+ { SIGTERM, "TERM" },
+#endif
+#ifdef SIGSTKFLT
+ { SIGSTKFLT, "STKFLT" },
+#endif
+#ifdef SIGCHLD
+ { SIGCHLD, "CHLD" },
+#endif
+#ifdef SIGCONT
+ { SIGCONT, "CONT" },
+#endif
+#ifdef SIGSTOP
+ { SIGSTOP, "STOP" },
+#endif
+#ifdef SIGTSTP
+ { SIGTSTP, "TSTP" },
+#endif
+#ifdef SIGTTIN
+ { SIGTTIN, "TTIN" },
+#endif
+#ifdef SIGTTOU
+ { SIGTTOU, "TTOU" },
+#endif
+#ifdef SIGURG
+ { SIGURG, "URG" },
+#endif
+#ifdef SIGXCPU
+ { SIGXCPU, "XCPU" },
+#endif
+#ifdef SIGXFSZ
+ { SIGXFSZ, "XFSZ" },
+#endif
+#ifdef SIGVTALRM
+ { SIGVTALRM, "VTALRM" },
+#endif
+#ifdef SIGPROF
+ { SIGPROF, "PROF" },
+#endif
+#ifdef SIGWINCH
+ { SIGWINCH, "WINCH" },
+#endif
+#ifdef SIGIO
+ { SIGIO, "IO" },
+#endif
+#ifdef SIGPWR
+ { SIGPWR, "PWR" },
+#endif
+#ifdef SIGSYS
+ { SIGSYS, "SYS" },
+#endif
+#ifdef disableSIGRTMIN /* initializer element is not constant */
+ { SIGRTMIN, "RTMIN" },
+#endif
+#ifdef disableSIGRTMAX /* initializer element is not constant */
+ { SIGRTMAX, "RTMAX" },
+#endif
+ };
+
+static void list (void)
+{
+ const struct signal *sig;
+
+ for (sig = sigtab; sig < sigtab + LENGTH (sigtab); sig++)
+ printf ("%2d\t%s\n", sig->signo, sig->name);
+ exit (EXIT_SUCCESS);
+}
+
+static
+#ifdef __GNUC__
+ __attribute__((__unused__))
+#endif
+ void fail (const char *where)
+{
+ fprintf (stderr, "Error parsing arguments: %s\n", where);
+ exit (EXIT_FAILURE);
+}
+
+static int parse_number (const char *text)
+{
+ char *end;
+ long val;
+
+ val = strtol (text, &end, 0);
+ if (val >= 0 && (int) val == val && (end == NULL || *end == 0))
+ return val;
+
+ return -1;
+}
+
+static int parse_signal (const char *text_orig)
+{
+ const char *text = text_orig;
+ const struct signal *sig;
+ int retval;
+
+ retval = parse_number (text);
+ if (retval >= 0)
+ return retval;
+
+ if (strncasecmp (text, "SIG", 3) == 0)
+ text += 3;
+ for (sig = sigtab; sig < sigtab + LENGTH (sigtab); sig++)
+ if (strcasecmp (sig->name, text) == 0)
+ return sig->signo;
+
+ fail (text_orig);
+ /* NOTREACHED */
+ return -1;
+}
+
+static void help (void)
+{
+ fputs ("\
+tgkill -h\n\
+tgkill -l\n\
+tgkill {-s sigspec | -n sigspec | -sigspec} pid ...\n\
+", stdout);
+ exit (EXIT_SUCCESS);
+}
+
+int main (int argc, char **argv)
+{
+ char **argp;
+ int signo;
+
+ if (argc == 2 && strcmp (argv[1], "-h") == 0)
+ help ();
+ if (argc == 2 && strcmp (argv[1], "-l") == 0)
+ list ();
+
+ if (argc > 3 && (strcmp (argv[1], "-s") == 0 || strcmp (argv[1], "-n") == 0))
+ {
+ signo = parse_signal (argv[2]);
+ argp = argv + 3;
+ }
+ else if (argc > 2 && argv[1][0] == '-')
+ {
+ signo = parse_signal (argv [1] + 1);
+ argp = argv + 2;
+ }
+ else
+ fail ("<general>");
+
+ while (argp < argv + argc)
+ {
+ const char *arg = *argp++;
+ int pid;
+
+ pid = parse_number (arg);
+ if (pid == -1)
+ fail (arg);
+
+ if (tkill (pid, signo) != 0)
+ perror (arg);
+ }
+
+ return EXIT_SUCCESS;
+}