/* Copyright (C) 2001-2005 Ben Kibbey 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 */ #include #include #include #include #include #include #include #include #include #include #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; }