165123Speter/*- 265123Speter * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org> 365123Speter * Copyright (c) 2000 Paul Saab <ps@FreeBSD.org> 465123Speter * All rights reserved. 565123Speter * 665123Speter * Redistribution and use in source and binary forms, with or without 765123Speter * modification, are permitted provided that the following conditions 865123Speter * are met: 965123Speter * 1. Redistributions of source code must retain the above copyright 1065123Speter * notice, this list of conditions and the following disclaimer. 1165123Speter * 2. Redistributions in binary form must reproduce the above copyright 1265123Speter * notice, this list of conditions and the following disclaimer in the 1365123Speter * documentation and/or other materials provided with the distribution. 1465123Speter * 1565123Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1665123Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1765123Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1865123Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1965123Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2065123Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2165123Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2265123Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2365123Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2465123Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2565123Speter * SUCH DAMAGE. 2665123Speter */ 2765123Speter 2865177Speter#include <sys/cdefs.h> 2999112Sobrien__FBSDID("$FreeBSD: releng/10.2/usr.bin/killall/killall.c 274471 2014-11-13 16:40:15Z smh $"); 3099112Sobrien 3165123Speter#include <sys/param.h> 32113277Smike#include <sys/jail.h> 3365123Speter#include <sys/stat.h> 34192896Sjamie#include <sys/uio.h> 3565123Speter#include <sys/user.h> 3665123Speter#include <sys/sysctl.h> 37200462Sdelphij#include <fcntl.h> 38200462Sdelphij#include <dirent.h> 39194869Sjamie#include <jail.h> 4065123Speter#include <stdio.h> 4165123Speter#include <stdlib.h> 4265123Speter#include <string.h> 4365123Speter#include <pwd.h> 4465123Speter#include <signal.h> 4565123Speter#include <regex.h> 4665123Speter#include <ctype.h> 4765123Speter#include <err.h> 4865123Speter#include <errno.h> 4965123Speter#include <unistd.h> 50132191Stjr#include <locale.h> 5165123Speter 5265177Speterstatic void __dead2 5365123Speterusage(void) 5465123Speter{ 5565123Speter 56252428Smjg fprintf(stderr, "usage: killall [-delmsqvz] [-help] [-I] [-j jail]\n"); 57113277Smike fprintf(stderr, 58124681Smaxim " [-u user] [-t tty] [-c cmd] [-SIGNAL] [cmd]...\n"); 5965123Speter fprintf(stderr, "At least one option or argument to specify processes must be given.\n"); 6065123Speter exit(1); 6165123Speter} 6265123Speter 6365123Speter 6465123Speterstatic void 6565123Speterprintsig(FILE *fp) 6665123Speter{ 6765123Speter const char *const * p; 6865123Speter int cnt; 6965123Speter int offset = 0; 7065123Speter 7165123Speter for (cnt = NSIG, p = sys_signame + 1; --cnt; ++p) { 72219347Sjilles offset += fprintf(fp, "%s ", *p); 7365123Speter if (offset >= 75 && cnt > 1) { 7465123Speter offset = 0; 7565123Speter fprintf(fp, "\n"); 7665123Speter } 7765123Speter } 7865123Speter fprintf(fp, "\n"); 7965123Speter} 8065123Speter 8165123Speterstatic void 8265123Speternosig(char *name) 8365123Speter{ 8465123Speter 8565123Speter warnx("unknown signal %s; valid signals:", name); 8665123Speter printsig(stderr); 8765123Speter exit(1); 8865123Speter} 8965123Speter 9065123Speterint 9165123Spetermain(int ac, char **av) 9265123Speter{ 93274471Ssmh char **saved_av; 94237844Skib struct kinfo_proc *procs, *newprocs; 9565123Speter struct stat sb; 9665127Speter struct passwd *pw; 9765123Speter regex_t rgx; 9865123Speter regmatch_t pmatch; 99237618Sdelphij int i, j, ch; 10065123Speter char buf[256]; 101237618Sdelphij char first; 10265123Speter char *user = NULL; 10365123Speter char *tty = NULL; 10465123Speter char *cmd = NULL; 105252428Smjg int qflag = 0; 10665123Speter int vflag = 0; 10765123Speter int sflag = 0; 10865123Speter int dflag = 0; 109125013Sdds int eflag = 0; 110237618Sdelphij int Iflag = 0; 111113277Smike int jflag = 0; 11265123Speter int mflag = 0; 11394689Sdes int zflag = 0; 11465123Speter uid_t uid = 0; 11565123Speter dev_t tdev = 0; 116124844Scperciva pid_t mypid; 11765123Speter char thiscmd[MAXCOMLEN + 1]; 11865123Speter pid_t thispid; 11965123Speter uid_t thisuid; 12065123Speter dev_t thistdev; 12165123Speter int sig = SIGTERM; 12265127Speter const char *const *p; 12365123Speter char *ep; 12465123Speter int errors = 0; 125113277Smike int jid; 12676678Sphk int mib[4]; 12765123Speter size_t miblen; 12865123Speter int st, nprocs; 12965123Speter size_t size; 13065123Speter int matched; 13165123Speter int killed = 0; 13265123Speter 133132191Stjr setlocale(LC_ALL, ""); 134132191Stjr 13565123Speter av++; 13665123Speter ac--; 13765123Speter 13865123Speter while (ac > 0) { 13965123Speter if (strcmp(*av, "-l") == 0) { 14065123Speter printsig(stdout); 14165123Speter exit(0); 14265123Speter } 14365177Speter if (strcmp(*av, "-help") == 0) 14465177Speter usage(); 14565123Speter if (**av == '-') { 14665123Speter ++*av; 14765123Speter switch (**av) { 148113277Smike case 'j': 149113277Smike ++*av; 150173502Sru if (**av == '\0') { 151113277Smike ++av; 152173502Sru --ac; 153173502Sru } 154113277Smike jflag++; 155173502Sru if (*av == NULL) 156192896Sjamie errx(1, "must specify jail"); 157194869Sjamie jid = jail_getid(*av); 158194869Sjamie if (jid < 0) 159194869Sjamie errx(1, "%s", jail_errmsg); 160113277Smike if (jail_attach(jid) == -1) 161192896Sjamie err(1, "jail_attach(%d)", jid); 162113277Smike break; 16365123Speter case 'u': 16465123Speter ++*av; 165173502Sru if (**av == '\0') { 16665123Speter ++av; 167173502Sru --ac; 168173502Sru } 169173502Sru if (*av == NULL) 170173502Sru errx(1, "must specify user"); 17165123Speter user = *av; 17265123Speter break; 17365123Speter case 't': 17465123Speter ++*av; 175173502Sru if (**av == '\0') { 17665123Speter ++av; 177173502Sru --ac; 178173502Sru } 179173502Sru if (*av == NULL) 180173502Sru errx(1, "must specify tty"); 18165123Speter tty = *av; 18265123Speter break; 18365123Speter case 'c': 18465123Speter ++*av; 185173502Sru if (**av == '\0') { 18665123Speter ++av; 187173502Sru --ac; 188173502Sru } 189173502Sru if (*av == NULL) 190173502Sru errx(1, "must specify procname"); 19165123Speter cmd = *av; 19265123Speter break; 193252428Smjg case 'q': 194252428Smjg qflag++; 195252428Smjg break; 19665123Speter case 'v': 19765123Speter vflag++; 19865123Speter break; 19965123Speter case 's': 20065123Speter sflag++; 20165123Speter break; 20265123Speter case 'd': 20365123Speter dflag++; 20465123Speter break; 205125013Sdds case 'e': 206125013Sdds eflag++; 207125013Sdds break; 20865123Speter case 'm': 20965123Speter mflag++; 21065123Speter break; 21194689Sdes case 'z': 21294689Sdes zflag++; 21394689Sdes break; 21465123Speter default: 215274471Ssmh saved_av = av; 216132193Stjr if (isalpha((unsigned char)**av)) { 217218285Sjilles if (strncasecmp(*av, "SIG", 3) == 0) 21865123Speter *av += 3; 21965123Speter for (sig = NSIG, p = sys_signame + 1; 22065123Speter --sig; ++p) 22165123Speter if (strcasecmp(*p, *av) == 0) { 22265123Speter sig = p - sys_signame; 22365123Speter break; 22465123Speter } 225274471Ssmh if (!sig) { 226274471Ssmh if (**saved_av == 'I') { 227274471Ssmh av = saved_av; 228274471Ssmh Iflag = 1; 229274471Ssmh break; 230274471Ssmh } else 231274471Ssmh nosig(*av); 232274471Ssmh } 233132193Stjr } else if (isdigit((unsigned char)**av)) { 23465123Speter sig = strtol(*av, &ep, 10); 23565123Speter if (!*av || *ep) 23665123Speter errx(1, "illegal signal number: %s", *av); 237132851Smaxim if (sig < 0 || sig >= NSIG) 23865123Speter nosig(*av); 23965123Speter } else 24065123Speter nosig(*av); 24165123Speter } 24265123Speter ++av; 24365123Speter --ac; 24465123Speter } else { 24565123Speter break; 24665123Speter } 24765123Speter } 24865123Speter 249113277Smike if (user == NULL && tty == NULL && cmd == NULL && !jflag && ac == 0) 25065123Speter usage(); 25165123Speter 25265123Speter if (tty) { 25365123Speter if (strncmp(tty, "/dev/", 5) == 0) 25465123Speter snprintf(buf, sizeof(buf), "%s", tty); 25565123Speter else if (strncmp(tty, "tty", 3) == 0) 25665123Speter snprintf(buf, sizeof(buf), "/dev/%s", tty); 25765123Speter else 25865123Speter snprintf(buf, sizeof(buf), "/dev/tty%s", tty); 25965123Speter if (stat(buf, &sb) < 0) 26065123Speter err(1, "stat(%s)", buf); 26165123Speter if (!S_ISCHR(sb.st_mode)) 26265123Speter errx(1, "%s: not a character device", buf); 26365123Speter tdev = sb.st_rdev; 26465123Speter if (dflag) 26565123Speter printf("ttydev:0x%x\n", tdev); 26665123Speter } 26765123Speter if (user) { 26878144Sobrien uid = strtol(user, &ep, 10); 26993432Sdwmalone if (*user == '\0' || *ep != '\0') { /* was it a number? */ 27078144Sobrien pw = getpwnam(user); 27178144Sobrien if (pw == NULL) 27278144Sobrien errx(1, "user %s does not exist", user); 27378144Sobrien uid = pw->pw_uid; 27478144Sobrien if (dflag) 27578144Sobrien printf("uid:%d\n", uid); 27678144Sobrien } 27765123Speter } else { 27865123Speter uid = getuid(); 27965123Speter if (uid != 0) { 28065123Speter pw = getpwuid(uid); 28165123Speter if (pw) 28265123Speter user = pw->pw_name; 28365123Speter if (dflag) 28465123Speter printf("uid:%d\n", uid); 28565123Speter } 28665123Speter } 28765123Speter size = 0; 28865123Speter mib[0] = CTL_KERN; 28965123Speter mib[1] = KERN_PROC; 29065123Speter 291119834Stjr if (user) { 292125013Sdds mib[2] = eflag ? KERN_PROC_UID : KERN_PROC_RUID; 29365123Speter mib[3] = uid; 294120500Stjr miblen = 4; 295119834Stjr } else if (tty) { 29665123Speter mib[2] = KERN_PROC_TTY; 29765123Speter mib[3] = tdev; 298120500Stjr miblen = 4; 299237845Skib } else { 300237845Skib mib[2] = KERN_PROC_PROC; 301237845Skib mib[3] = 0; 302237845Skib miblen = 3; 30365123Speter } 30465123Speter 305237844Skib procs = NULL; 30665123Speter st = sysctl(mib, miblen, NULL, &size, NULL, 0); 30765123Speter do { 30865123Speter size += size / 10; 30965123Speter newprocs = realloc(procs, size); 310237844Skib if (newprocs == NULL) { 311237844Skib free(procs); 312237844Skib err(1, "could not reallocate memory"); 31365123Speter } 31465123Speter procs = newprocs; 31565123Speter st = sysctl(mib, miblen, procs, &size, NULL, 0); 31665123Speter } while (st == -1 && errno == ENOMEM); 31765123Speter if (st == -1) 31865123Speter err(1, "could not sysctl(KERN_PROC)"); 31965123Speter if (size % sizeof(struct kinfo_proc) != 0) { 320132192Stjr fprintf(stderr, "proc size mismatch (%zu total, %zu chunks)\n", 32165123Speter size, sizeof(struct kinfo_proc)); 322237846Skib fprintf(stderr, "userland out of sync with kernel\n"); 32365123Speter exit(1); 32465123Speter } 32565123Speter nprocs = size / sizeof(struct kinfo_proc); 32665123Speter if (dflag) 32765123Speter printf("nprocs %d\n", nprocs); 328124844Scperciva mypid = getpid(); 32965123Speter 33065123Speter for (i = 0; i < nprocs; i++) { 331237847Skib if (procs[i].ki_stat == SZOMB && !zflag) 33294689Sdes continue; 33369941Sjhb thispid = procs[i].ki_pid; 334185074Sdelphij strlcpy(thiscmd, procs[i].ki_comm, sizeof(thiscmd)); 33569941Sjhb thistdev = procs[i].ki_tdev; 336125013Sdds if (eflag) 337125013Sdds thisuid = procs[i].ki_uid; /* effective uid */ 338125013Sdds else 339125013Sdds thisuid = procs[i].ki_ruid; /* real uid */ 34065123Speter 341124844Scperciva if (thispid == mypid) 342124844Scperciva continue; 34365123Speter matched = 1; 34465123Speter if (user) { 34565123Speter if (thisuid != uid) 34665123Speter matched = 0; 34765123Speter } 34865123Speter if (tty) { 34965123Speter if (thistdev != tdev) 35065123Speter matched = 0; 35165123Speter } 35265123Speter if (cmd) { 35365123Speter if (mflag) { 35465123Speter if (regcomp(&rgx, cmd, 35565123Speter REG_EXTENDED|REG_NOSUB) != 0) { 35665123Speter mflag = 0; 35765123Speter warnx("%s: illegal regexp", cmd); 35865123Speter } 35965123Speter } 36065123Speter if (mflag) { 36165123Speter pmatch.rm_so = 0; 36265123Speter pmatch.rm_eo = strlen(thiscmd); 36365123Speter if (regexec(&rgx, thiscmd, 0, &pmatch, 36465123Speter REG_STARTEND) != 0) 36565123Speter matched = 0; 36665123Speter regfree(&rgx); 36765123Speter } else { 36872497Speter if (strncmp(thiscmd, cmd, MAXCOMLEN) != 0) 36965123Speter matched = 0; 37065123Speter } 37165123Speter } 372113277Smike if (jflag && thispid == getpid()) 373113277Smike matched = 0; 37465123Speter if (matched == 0) 37565123Speter continue; 37671309Sache if (ac > 0) 37771309Sache matched = 0; 37865123Speter for (j = 0; j < ac; j++) { 37965123Speter if (mflag) { 38065123Speter if (regcomp(&rgx, av[j], 38165123Speter REG_EXTENDED|REG_NOSUB) != 0) { 38265123Speter mflag = 0; 38365123Speter warnx("%s: illegal regexp", av[j]); 38465123Speter } 38565123Speter } 38665123Speter if (mflag) { 38765123Speter pmatch.rm_so = 0; 38865123Speter pmatch.rm_eo = strlen(thiscmd); 38965123Speter if (regexec(&rgx, thiscmd, 0, &pmatch, 39065123Speter REG_STARTEND) == 0) 39165123Speter matched = 1; 39265123Speter regfree(&rgx); 39365123Speter } else { 39465123Speter if (strcmp(thiscmd, av[j]) == 0) 39565123Speter matched = 1; 39665123Speter } 39765123Speter if (matched) 39865123Speter break; 39965123Speter } 400237618Sdelphij if (matched != 0 && Iflag) { 401237618Sdelphij printf("Send signal %d to %s (pid %d uid %d)? ", 402237618Sdelphij sig, thiscmd, thispid, thisuid); 403237618Sdelphij fflush(stdout); 404237618Sdelphij first = ch = getchar(); 405237618Sdelphij while (ch != '\n' && ch != EOF) 406237618Sdelphij ch = getchar(); 407237618Sdelphij if (first != 'y' && first != 'Y') 408237618Sdelphij matched = 0; 409237618Sdelphij } 41065123Speter if (matched == 0) 41165123Speter continue; 41265123Speter if (dflag) 41365123Speter printf("sig:%d, cmd:%s, pid:%d, dev:0x%x uid:%d\n", sig, 41465123Speter thiscmd, thispid, thistdev, thisuid); 41565123Speter 41665123Speter if (vflag || sflag) 417219347Sjilles printf("kill -%s %d\n", sys_signame[sig], thispid); 41865123Speter 41965123Speter killed++; 42065123Speter if (!dflag && !sflag) { 42165123Speter if (kill(thispid, sig) < 0 /* && errno != ESRCH */ ) { 42296976Sdd warn("warning: kill -%s %d", 423219347Sjilles sys_signame[sig], thispid); 42465123Speter errors = 1; 42565123Speter } 42665123Speter } 42765123Speter } 42865123Speter if (killed == 0) { 429252428Smjg if (!qflag) 430252428Smjg fprintf(stderr, "No matching processes %swere found\n", 431252428Smjg getuid() != 0 ? "belonging to you " : ""); 43265123Speter errors = 1; 43365123Speter } 43465123Speter exit(errors); 43565123Speter} 436