/*
Copyright (C) 2001-2005 Ben Kibbey <bjk@arbornet.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
*
* Try and kill off a users login process(s). This needs the userinfo utility
* from http://arbornet.org/~bjk/userinfo/ with the login.so module loaded
* and chained (-x) before this module.
*
* Compile with:
* gcc -O2 -g -Wall -shared -fPIC -o kill.so kill.c
*
* Run with:
* ui -x login.so -p -- -O ./kill.so --
*
* Or with any other options you'd want. Just make sure the first option to
* the login module is -p.
*
* Ben Kibbey <bjk@arbornet.org>
*/
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include <err.h>
#include <limits.h>
#define KILL_OPTION_STRING "s:"
void add_string(char ***, char *);
static int *do_sigs;
static int sig_index;
struct signals {
int sig;
char *name;
};
static struct signals sigs[] = {
{1, "SIGHUP"},
{2, "SIGINT"},
{3, "SIGQUIT"},
{4, "SIGILL"},
{6, "SIGABRT"},
{8, "SIGFPE"},
{9, "SIGKILL"},
{11, "SIGSEGV"},
{13, "SIGPIPE"},
{14, "SIGALRM"},
{15, "SIGTERM"},
#ifdef __i386__
/* or PPC */
{10, "SIGUSR1"},
{12, "SIGUSR2"},
{17, "SIGCHLD"},
{18, "SIGCONT"},
{19, "SIGSTOP"},
{20, "SIGTSTP"},
{21, "SIGTTIN"},
{22, "SIGTTOU"},
#else
/* Alpha or SPARC. */
{30, "SIGUSR1"},
{31, "SIGUSR2"},
{20, "SIGCHLD"},
{19, "SIGCONT"},
{17, "SIGSTOP"},
{18, "SIGTSTP"},
{21, "SIGTTIN"},
{22, "SIGTTOU"},
#endif
{-1, NULL}
};
void ui_module_init(int *chainable)
{
do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
do_sigs[sig_index++] = 1;
do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
do_sigs[sig_index++] = 9;
*chainable = 1;
return;
}
void ui_module_exit()
{
if (do_sigs)
free(do_sigs);
return;
}
void ui_module_help()
{
printf(" Kill a login process; requires login.so -p (-s SIGHUP,9):\n");
printf("\t-s Send these comma separated signals (integers or strings).\n\n");
return;
}
char *ui_module_options_init(char **defaults)
{
*defaults = NULL;
return KILL_OPTION_STRING;
}
int ui_module_options(int argc, char **argv)
{
int opt;
while ((opt = getopt(argc, argv, KILL_OPTION_STRING)) != -1) {
char *tmp;
switch (opt) {
case 's':
sig_index = 0;
again:
while ((tmp = strsep(&optarg, ",")) != NULL) {
int i;
int sig;
if (isdigit(*tmp)) {
sig = atoi(tmp);
for (i = 0; sigs[i].sig != -1; i++) {
if (sig == sigs[i].sig) {
do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
do_sigs[sig_index++] = sig;
goto again;
}
}
}
for (i = 0; sigs[i].name; i++) {
if (strcasecmp(tmp, sigs[i].name) == 0) {
do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
do_sigs[sig_index++] = sigs[i].sig;
goto again;
}
}
warnx("kill.so: invalid signal -- %s", tmp);
return 1;
}
break;
case '?':
warnx("kill.so: invalid option -- %c", optopt);
default:
return 1;
}
}
return 0;
}
static int killit(pid_t pid, int sig)
{
if (kill(pid, 0) == -1)
return 1;
if (kill(pid, sig) == -1)
return 1;
return 0;
}
int ui_module_exec(char ***result, const struct passwd *pw, const int
multi, const int verbose, const char *tf)
{
pid_t pid;
char **strings = NULL;
int i;
char line[LINE_MAX] = {'\0'};
char *tmp;
char m[2] = {multi, '\0'};
strings = *result;
if (*result == NULL)
add_string(&strings, "!");
else {
/* There may be more than one pid for multiple logins. Separated the
* output with the multi-string deliminator and send the signals to each
* pid. */
while ((tmp = strsep(&*result[0], m)) != NULL) {
char *s = "!";
if (isdigit(*tmp) == 0) {
strncat(line, "!", sizeof(line));
strncat(line, m, sizeof(line));
}
else {
pid = atol(tmp);
for (i = 0; i < sig_index; i++) {
if (killit(pid, do_sigs[i]) == 0) {
s = "1";
break;
}
s = "0";
}
strncat(line, s, sizeof(line));
strncat(line, m, sizeof(line));
}
}
}
line[strlen(line) - 1] = '\0';
add_string(&strings, line);
*result = strings;
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1