Fix potential buffer overflow.
[userinfo.git] / contrib / kill.c
blob2a8823270f3f14697fac7cff04e27de04068df7f
1 /*
2 Copyright (C) 2001-2011 Ben Kibbey <bjk@luxsci.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
20 * Try and kill off a users login process(s). This needs the userinfo utility
21 * from http://userinfo.sourceforge.net/ with the login.so module loaded
22 * and chained (-x) before this module.
24 * Compile with:
25 * gcc -O2 -g -Wall -shared -fPIC -o kill.so kill.c
27 * Run with:
28 * ui -x login.so -p -- -O ./kill.so --
30 * Or with any other options you'd want. Just make sure the first option to
31 * the login module is -p.
33 * Ben Kibbey <bjk@luxsci.net>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <pwd.h>
38 #include <sys/types.h>
39 #include <signal.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <getopt.h>
43 #include <err.h>
44 #include <limits.h>
46 #define KILL_OPTION_STRING "s:"
48 void add_string(char ***, char *);
50 static int *do_sigs;
51 static int sig_index;
53 struct signals {
54 int sig;
55 char *name;
58 static struct signals sigs[] = {
59 {1, "SIGHUP"},
60 {2, "SIGINT"},
61 {3, "SIGQUIT"},
62 {4, "SIGILL"},
63 {6, "SIGABRT"},
64 {8, "SIGFPE"},
65 {9, "SIGKILL"},
66 {11, "SIGSEGV"},
67 {13, "SIGPIPE"},
68 {14, "SIGALRM"},
69 {15, "SIGTERM"},
70 #ifdef __i386__
71 /* or PPC */
72 {10, "SIGUSR1"},
73 {12, "SIGUSR2"},
74 {17, "SIGCHLD"},
75 {18, "SIGCONT"},
76 {19, "SIGSTOP"},
77 {20, "SIGTSTP"},
78 {21, "SIGTTIN"},
79 {22, "SIGTTOU"},
80 #else
81 /* Alpha or SPARC. */
82 {30, "SIGUSR1"},
83 {31, "SIGUSR2"},
84 {20, "SIGCHLD"},
85 {19, "SIGCONT"},
86 {17, "SIGSTOP"},
87 {18, "SIGTSTP"},
88 {21, "SIGTTIN"},
89 {22, "SIGTTOU"},
90 #endif
91 {-1, NULL}
94 void ui_module_init(int *chainable)
96 do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
97 do_sigs[sig_index++] = 1;
98 do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
99 do_sigs[sig_index++] = 9;
100 *chainable = 1;
101 return;
104 void ui_module_exit()
106 if (do_sigs)
107 free(do_sigs);
109 return;
112 void ui_module_help()
114 printf(" Kill a login process; requires login.so -p (-s SIGHUP,9):\n");
115 printf("\t-s Send these comma separated signals (integers or strings).\n\n");
116 return;
119 char *ui_module_options_init(char **defaults)
121 *defaults = NULL;
122 return KILL_OPTION_STRING;
125 int ui_module_options(int argc, char **argv)
127 int opt;
129 while ((opt = getopt(argc, argv, KILL_OPTION_STRING)) != -1) {
130 char *tmp;
132 switch (opt) {
133 case 's':
134 sig_index = 0;
136 again:
137 while ((tmp = strsep(&optarg, ",")) != NULL) {
138 int i;
139 int sig;
141 if (isdigit(*tmp)) {
142 sig = atoi(tmp);
144 for (i = 0; sigs[i].sig != -1; i++) {
145 if (sig == sigs[i].sig) {
146 do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
147 do_sigs[sig_index++] = sig;
148 goto again;
153 for (i = 0; sigs[i].name; i++) {
154 if (strcasecmp(tmp, sigs[i].name) == 0) {
155 do_sigs = realloc(do_sigs, (sig_index + 2) * sizeof(int *));
156 do_sigs[sig_index++] = sigs[i].sig;
157 goto again;
161 warnx("kill.so: invalid signal -- %s", tmp);
162 return 1;
164 break;
165 case '?':
166 warnx("kill.so: invalid option -- %c", optopt);
167 default:
168 return 1;
172 return 0;
175 static int killit(pid_t pid, int sig)
177 if (kill(pid, 0) == -1)
178 return 1;
180 if (kill(pid, sig) == -1)
181 return 1;
183 return 0;
186 int ui_module_exec(char ***result, const struct passwd *pw, const int
187 multi, const int verbose, const char *tf)
189 pid_t pid;
190 char **strings = NULL;
191 int i;
192 char line[LINE_MAX] = {'\0'};
193 char *tmp;
194 char m[2] = {multi, '\0'};
196 strings = *result;
198 if (*result == NULL)
199 add_string(&strings, "!");
200 else {
201 /* There may be more than one pid for multiple logins. Separated the
202 * output with the multi-string deliminator and send the signals to each
203 * pid. */
204 while ((tmp = strsep(&*result[0], m)) != NULL) {
205 char *s = "!";
207 if (isdigit(*tmp) == 0) {
208 strncat(line, "!", sizeof(line)-strlen(line)-1);
209 strncat(line, m, sizeof(line)-strlen(line)-1);
211 else {
212 pid = atol(tmp);
214 for (i = 0; i < sig_index; i++) {
215 if (killit(pid, do_sigs[i]) == 0) {
216 s = "1";
217 break;
220 s = "0";
223 strncat(line, s, sizeof(line)-strlen(line)-1);
224 strncat(line, m, sizeof(line)-strlen(line)-1);
229 line[strlen(line) - 1] = '\0';
230 add_string(&strings, line);
231 *result = strings;
232 return 0;