view toys/kill.c @ 490:96a5e66a7dae

Add new kill toy. Used to send signals to a process or a process group.
author Daniel Walter <d.walter@0x90.at>
date Tue, 21 Feb 2012 19:45:19 -0600
parents
children c9aaceccd6bd
line wrap: on
line source

/* vi: set sw=4 ts=4:
 *
 * kill.c - a program to send signals to processes
 *
 * Copyright 2012 Daniel Walter <d.walter@0x90.at>
 *
 * See http://opengroup.org/onlinepubs/9699919799/utilities/kill.html

USE_KILL(NEWTOY(kill, NULL, TOYFLAG_BIN))

config KILL
	bool "kill"
	default y
	help
	  usage: kill [-l signal_number | -s signal_name | -signal_name | -signal_number] pid...

	  Send a signal to a process

*/

#include "toys.h"

#define TT this.kill

typedef struct {
	int signum;
	char *signame;
} signals_t;

const signals_t signals[] = {
	{ 1, "HUP"},
	{ 2, "INT"},
	{ 3, "QUIT"},
	{ 4, "ILL"},
	{ 5, "TRAP"},
	{ 6, "ABRT"},
	{ 7, "BUS"},
	{ 8, "FPE"},
	{ 9, "KILL"},
	{ 10, "USR1"},
	{ 11, "SEGV"},
	{ 12, "USR2"},
	{ 13, "PIPE"},
	{ 14, "ALRM"},
	{ 15, "TERM"},
	{ 16, "STKFLT"},
	{ 17, "CHLD"},
	{ 18, "CONT"},
	{ 19, "STOP"},
	{ 20, "TSTP"},
	{ 21, "TTIN"},
	{ 22, "TTOU"},
	{ 23, "URG"},
	{ 24, "XCPU"},
	{ 25, "XFSZ"},
	{ 26, "VTALRM"},
	{ 27, "PROF"},
	{ 28, "WINCH"},
	{ 29, "POLL"},
	{ 30, "PWR"},
	{ 31, "SYS"},
	/* terminator */
	{ -1, NULL},
};

static char* signum_to_signame(int sig)
{
	int i = 0;
	for (;;) {
		if (signals[i].signum == sig)
			return signals[i].signame;

		if (signals[++i].signum == -1)
			break;
	}
	return NULL;
}

static int signame_to_signum(char *signame)
{
	int i=0;
	for (;;) {
		if (!strcmp(signals[i].signame, signame))
			return signals[i].signum;
		if (signals[++i].signum == -1)
			break;
	}
	return -1;
}

static int send_signal(int sig, pid_t pid)
{
	if (kill(pid, sig) < 0) {
		perror("kill");
		return -1;
	}
	return 0;
}

static void list_all_signals()
{
	int i = 0;
	for (;;) {
		printf("%s ", signals[i++].signame);
		if (i % 16 == 0)
			printf("\n");
		if (signals[i].signum == -1)
			break;
	}
	printf("\n");
}

static int list_signal(int signum)
{
	char *signam = signum_to_signame(signum);
	if (signam) {
		printf("%s\n", signam);
		return 0;
	} else {
		printf("Unknown signal %d\n", signum);
		return -1;
	}
}

static int list_signal_by_name(char *signame)
{
	int signum = signame_to_signum(signame);
	if (signum > 0) {
		printf("%d\n", signum);
		return 0;
	} else {
		printf("Unknown signal %s\n", signame);
		return -1;
	}
} 

void kill_main(void)
{
	int signum = 0;
	int have_signal = 0;
	char *signame, *tmp;
	pid_t pid;
	while (*toys.optargs) {
		char *arg = *(toys.optargs++);
		if (arg[0] == '-' && !have_signal) {
			arg++;
			switch(arg[0]) {
			case 'l':
				if (!*toys.optargs)
					list_all_signals();
				else {
					signum = strtol(*(toys.optargs), &signame, 10);
					if (signame == *(toys.optargs))
						list_signal_by_name(signame);
					else
						list_signal(signum);
				}
				return;
			case 's':
				arg = *(toys.optargs++);
			default:
				signum = strtol(arg, &signame, 10);
				if (signame == arg) {
					signum = signame_to_signum(signame);
					if (signum < 0) {
						toys.exitval = EXIT_FAILURE;
						return;
					}
				}
				have_signal = 1;
			}
		} else {
			/* pids */
			pid = strtol(arg, &tmp, 10);
			if (tmp == arg) {
				toys.exitval = EXIT_FAILURE;
				return;
			}
			if (send_signal(signum, pid) < 0) {
				toys.exitval = EXIT_FAILURE;
				return;
			}
				
		}
	}
}