11198f21cSPeter Wemm /*- 21198f21cSPeter Wemm * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org> 31198f21cSPeter Wemm * Copyright (c) 2000 Paul Saab <ps@FreeBSD.org> 41198f21cSPeter Wemm * All rights reserved. 51198f21cSPeter Wemm * 61198f21cSPeter Wemm * Redistribution and use in source and binary forms, with or without 71198f21cSPeter Wemm * modification, are permitted provided that the following conditions 81198f21cSPeter Wemm * are met: 91198f21cSPeter Wemm * 1. Redistributions of source code must retain the above copyright 101198f21cSPeter Wemm * notice, this list of conditions and the following disclaimer. 111198f21cSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 121198f21cSPeter Wemm * notice, this list of conditions and the following disclaimer in the 131198f21cSPeter Wemm * documentation and/or other materials provided with the distribution. 141198f21cSPeter Wemm * 151198f21cSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 161198f21cSPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 171198f21cSPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181198f21cSPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 191198f21cSPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 201198f21cSPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 211198f21cSPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 221198f21cSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 231198f21cSPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 241198f21cSPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 251198f21cSPeter Wemm * SUCH DAMAGE. 261198f21cSPeter Wemm */ 271198f21cSPeter Wemm 288750ed5fSPeter Wemm #include <sys/cdefs.h> 29e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 30e026a48cSDavid E. O'Brien 311198f21cSPeter Wemm #include <sys/param.h> 32ebf5d9bcSMike Barcroft #include <sys/jail.h> 331198f21cSPeter Wemm #include <sys/stat.h> 341198f21cSPeter Wemm #include <sys/user.h> 351198f21cSPeter Wemm #include <sys/sysctl.h> 361198f21cSPeter Wemm #include <fcntl.h> 371198f21cSPeter Wemm #include <dirent.h> 381198f21cSPeter Wemm #include <stdio.h> 391198f21cSPeter Wemm #include <stdlib.h> 401198f21cSPeter Wemm #include <string.h> 411198f21cSPeter Wemm #include <pwd.h> 421198f21cSPeter Wemm #include <signal.h> 431198f21cSPeter Wemm #include <regex.h> 441198f21cSPeter Wemm #include <ctype.h> 451198f21cSPeter Wemm #include <err.h> 461198f21cSPeter Wemm #include <errno.h> 471198f21cSPeter Wemm #include <unistd.h> 481198f21cSPeter Wemm 498750ed5fSPeter Wemm static void __dead2 501198f21cSPeter Wemm usage(void) 511198f21cSPeter Wemm { 521198f21cSPeter Wemm 53ebf5d9bcSMike Barcroft fprintf(stderr, "usage: killall [-l] [-v] [-m] [-sig] [-j jid]\n"); 54ebf5d9bcSMike Barcroft fprintf(stderr, 55ebf5d9bcSMike Barcroft " [-u user] [-t tty] [-c cmd] [cmd]...\n"); 561198f21cSPeter Wemm fprintf(stderr, "At least one option or argument to specify processes must be given.\n"); 571198f21cSPeter Wemm exit(1); 581198f21cSPeter Wemm } 591198f21cSPeter Wemm 601198f21cSPeter Wemm static char * 611198f21cSPeter Wemm upper(const char *str) 621198f21cSPeter Wemm { 631198f21cSPeter Wemm static char buf[80]; 641198f21cSPeter Wemm char *s; 651198f21cSPeter Wemm 661198f21cSPeter Wemm strncpy(buf, str, sizeof(buf)); 671198f21cSPeter Wemm buf[sizeof(buf) - 1] = '\0'; 68a0388467SPeter Wemm for (s = buf; *s; s++) 691198f21cSPeter Wemm *s = toupper(*s); 701198f21cSPeter Wemm return buf; 711198f21cSPeter Wemm } 721198f21cSPeter Wemm 731198f21cSPeter Wemm 741198f21cSPeter Wemm static void 751198f21cSPeter Wemm printsig(FILE *fp) 761198f21cSPeter Wemm { 771198f21cSPeter Wemm const char *const * p; 781198f21cSPeter Wemm int cnt; 791198f21cSPeter Wemm int offset = 0; 801198f21cSPeter Wemm 811198f21cSPeter Wemm for (cnt = NSIG, p = sys_signame + 1; --cnt; ++p) { 821198f21cSPeter Wemm offset += fprintf(fp, "%s ", upper(*p)); 831198f21cSPeter Wemm if (offset >= 75 && cnt > 1) { 841198f21cSPeter Wemm offset = 0; 851198f21cSPeter Wemm fprintf(fp, "\n"); 861198f21cSPeter Wemm } 871198f21cSPeter Wemm } 881198f21cSPeter Wemm fprintf(fp, "\n"); 891198f21cSPeter Wemm } 901198f21cSPeter Wemm 911198f21cSPeter Wemm static void 921198f21cSPeter Wemm nosig(char *name) 931198f21cSPeter Wemm { 941198f21cSPeter Wemm 951198f21cSPeter Wemm warnx("unknown signal %s; valid signals:", name); 961198f21cSPeter Wemm printsig(stderr); 971198f21cSPeter Wemm exit(1); 981198f21cSPeter Wemm } 991198f21cSPeter Wemm 1001198f21cSPeter Wemm int 1011198f21cSPeter Wemm main(int ac, char **av) 1021198f21cSPeter Wemm { 1031198f21cSPeter Wemm struct kinfo_proc *procs = NULL, *newprocs; 1041198f21cSPeter Wemm struct stat sb; 1051198f21cSPeter Wemm struct passwd *pw; 1061198f21cSPeter Wemm regex_t rgx; 1071198f21cSPeter Wemm regmatch_t pmatch; 1081198f21cSPeter Wemm int i, j; 1091198f21cSPeter Wemm char buf[256]; 1101198f21cSPeter Wemm char *user = NULL; 1111198f21cSPeter Wemm char *tty = NULL; 1121198f21cSPeter Wemm char *cmd = NULL; 1131198f21cSPeter Wemm int vflag = 0; 1141198f21cSPeter Wemm int sflag = 0; 1151198f21cSPeter Wemm int dflag = 0; 116ebf5d9bcSMike Barcroft int jflag = 0; 1171198f21cSPeter Wemm int mflag = 0; 118a2fefc8dSDag-Erling Smørgrav int zflag = 0; 1191198f21cSPeter Wemm uid_t uid = 0; 1201198f21cSPeter Wemm dev_t tdev = 0; 1211198f21cSPeter Wemm char thiscmd[MAXCOMLEN + 1]; 1221198f21cSPeter Wemm pid_t thispid; 1231198f21cSPeter Wemm uid_t thisuid; 1241198f21cSPeter Wemm dev_t thistdev; 1251198f21cSPeter Wemm int sig = SIGTERM; 1261198f21cSPeter Wemm const char *const *p; 1271198f21cSPeter Wemm char *ep; 1281198f21cSPeter Wemm int errors = 0; 129ebf5d9bcSMike Barcroft int jid; 13049a4598bSPoul-Henning Kamp int mib[4]; 1311198f21cSPeter Wemm size_t miblen; 1321198f21cSPeter Wemm int st, nprocs; 1331198f21cSPeter Wemm size_t size; 1341198f21cSPeter Wemm int matched; 1351198f21cSPeter Wemm int killed = 0; 1361198f21cSPeter Wemm 1371198f21cSPeter Wemm av++; 1381198f21cSPeter Wemm ac--; 1391198f21cSPeter Wemm 1401198f21cSPeter Wemm while (ac > 0) { 1411198f21cSPeter Wemm if (strcmp(*av, "-l") == 0) { 1421198f21cSPeter Wemm printsig(stdout); 1431198f21cSPeter Wemm exit(0); 1441198f21cSPeter Wemm } 1458750ed5fSPeter Wemm if (strcmp(*av, "-help") == 0) 1468750ed5fSPeter Wemm usage(); 1471198f21cSPeter Wemm if (**av == '-') { 1481198f21cSPeter Wemm ++*av; 1491198f21cSPeter Wemm switch (**av) { 150ebf5d9bcSMike Barcroft case 'j': 151ebf5d9bcSMike Barcroft ++*av; 152ebf5d9bcSMike Barcroft if (**av == '\0') 153ebf5d9bcSMike Barcroft ++av; 154ebf5d9bcSMike Barcroft --ac; 155ebf5d9bcSMike Barcroft jflag++; 1566a31ec40SWarner Losh if (!*av) 1576a31ec40SWarner Losh errx(1, "must specify jid"); 158ebf5d9bcSMike Barcroft jid = strtol(*av, &ep, 10); 159ebf5d9bcSMike Barcroft if (!*av || *ep) 160ebf5d9bcSMike Barcroft errx(1, "illegal jid: %s", *av); 161ebf5d9bcSMike Barcroft if (jail_attach(jid) == -1) 162ebf5d9bcSMike Barcroft err(1, "jail_attach(): %d", jid); 163ebf5d9bcSMike Barcroft break; 1641198f21cSPeter Wemm case 'u': 1651198f21cSPeter Wemm ++*av; 1661198f21cSPeter Wemm if (**av == '\0') 1671198f21cSPeter Wemm ++av; 1681198f21cSPeter Wemm --ac; 1691198f21cSPeter Wemm user = *av; 1701198f21cSPeter Wemm break; 1711198f21cSPeter Wemm case 't': 1721198f21cSPeter Wemm ++*av; 1731198f21cSPeter Wemm if (**av == '\0') 1741198f21cSPeter Wemm ++av; 1751198f21cSPeter Wemm --ac; 1761198f21cSPeter Wemm tty = *av; 1771198f21cSPeter Wemm break; 1781198f21cSPeter Wemm case 'c': 1791198f21cSPeter Wemm ++*av; 1801198f21cSPeter Wemm if (**av == '\0') 1811198f21cSPeter Wemm ++av; 1821198f21cSPeter Wemm --ac; 1831198f21cSPeter Wemm cmd = *av; 1841198f21cSPeter Wemm break; 1851198f21cSPeter Wemm case 'v': 1861198f21cSPeter Wemm vflag++; 1871198f21cSPeter Wemm break; 1881198f21cSPeter Wemm case 's': 1891198f21cSPeter Wemm sflag++; 1901198f21cSPeter Wemm break; 1911198f21cSPeter Wemm case 'd': 1921198f21cSPeter Wemm dflag++; 1931198f21cSPeter Wemm break; 1941198f21cSPeter Wemm case 'm': 1951198f21cSPeter Wemm mflag++; 1961198f21cSPeter Wemm break; 197a2fefc8dSDag-Erling Smørgrav case 'z': 198a2fefc8dSDag-Erling Smørgrav zflag++; 199a2fefc8dSDag-Erling Smørgrav break; 2001198f21cSPeter Wemm default: 2011198f21cSPeter Wemm if (isalpha(**av)) { 2021198f21cSPeter Wemm if (strncasecmp(*av, "sig", 3) == 0) 2031198f21cSPeter Wemm *av += 3; 2041198f21cSPeter Wemm for (sig = NSIG, p = sys_signame + 1; 2051198f21cSPeter Wemm --sig; ++p) 2061198f21cSPeter Wemm if (strcasecmp(*p, *av) == 0) { 2071198f21cSPeter Wemm sig = p - sys_signame; 2081198f21cSPeter Wemm break; 2091198f21cSPeter Wemm } 2101198f21cSPeter Wemm if (!sig) 2111198f21cSPeter Wemm nosig(*av); 2121198f21cSPeter Wemm } else if (isdigit(**av)) { 2131198f21cSPeter Wemm sig = strtol(*av, &ep, 10); 2141198f21cSPeter Wemm if (!*av || *ep) 2151198f21cSPeter Wemm errx(1, "illegal signal number: %s", *av); 2161198f21cSPeter Wemm if (sig < 0 || sig > NSIG) 2171198f21cSPeter Wemm nosig(*av); 2181198f21cSPeter Wemm } else 2191198f21cSPeter Wemm nosig(*av); 2201198f21cSPeter Wemm } 2211198f21cSPeter Wemm ++av; 2221198f21cSPeter Wemm --ac; 2231198f21cSPeter Wemm } else { 2241198f21cSPeter Wemm break; 2251198f21cSPeter Wemm } 2261198f21cSPeter Wemm } 2271198f21cSPeter Wemm 228ebf5d9bcSMike Barcroft if (user == NULL && tty == NULL && cmd == NULL && !jflag && ac == 0) 2291198f21cSPeter Wemm usage(); 2301198f21cSPeter Wemm 2311198f21cSPeter Wemm if (tty) { 2321198f21cSPeter Wemm if (strncmp(tty, "/dev/", 5) == 0) 2331198f21cSPeter Wemm snprintf(buf, sizeof(buf), "%s", tty); 2341198f21cSPeter Wemm else if (strncmp(tty, "tty", 3) == 0) 2351198f21cSPeter Wemm snprintf(buf, sizeof(buf), "/dev/%s", tty); 2361198f21cSPeter Wemm else 2371198f21cSPeter Wemm snprintf(buf, sizeof(buf), "/dev/tty%s", tty); 2381198f21cSPeter Wemm if (stat(buf, &sb) < 0) 2391198f21cSPeter Wemm err(1, "stat(%s)", buf); 2401198f21cSPeter Wemm if (!S_ISCHR(sb.st_mode)) 2411198f21cSPeter Wemm errx(1, "%s: not a character device", buf); 2421198f21cSPeter Wemm tdev = sb.st_rdev; 2431198f21cSPeter Wemm if (dflag) 2441198f21cSPeter Wemm printf("ttydev:0x%x\n", tdev); 2451198f21cSPeter Wemm } 2461198f21cSPeter Wemm if (user) { 2470d1b691eSDavid E. O'Brien uid = strtol(user, &ep, 10); 248fb757ee2SDavid Malone if (*user == '\0' || *ep != '\0') { /* was it a number? */ 2491198f21cSPeter Wemm pw = getpwnam(user); 2501198f21cSPeter Wemm if (pw == NULL) 2511198f21cSPeter Wemm errx(1, "user %s does not exist", user); 2521198f21cSPeter Wemm uid = pw->pw_uid; 2531198f21cSPeter Wemm if (dflag) 2541198f21cSPeter Wemm printf("uid:%d\n", uid); 2550d1b691eSDavid E. O'Brien } 2561198f21cSPeter Wemm } else { 2571198f21cSPeter Wemm uid = getuid(); 2581198f21cSPeter Wemm if (uid != 0) { 2591198f21cSPeter Wemm pw = getpwuid(uid); 2601198f21cSPeter Wemm if (pw) 2611198f21cSPeter Wemm user = pw->pw_name; 2621198f21cSPeter Wemm if (dflag) 2631198f21cSPeter Wemm printf("uid:%d\n", uid); 2641198f21cSPeter Wemm } 2651198f21cSPeter Wemm } 2661198f21cSPeter Wemm size = 0; 2671198f21cSPeter Wemm mib[0] = CTL_KERN; 2681198f21cSPeter Wemm mib[1] = KERN_PROC; 2692c801d3dSTim J. Robbins mib[2] = KERN_PROC_PROC; 2701198f21cSPeter Wemm mib[3] = 0; 271f2dd06abSTim J. Robbins miblen = 3; 2721198f21cSPeter Wemm 2732c801d3dSTim J. Robbins if (user) { 27488522a2eSPaul Saab mib[2] = KERN_PROC_RUID; 2751198f21cSPeter Wemm mib[3] = uid; 276f2dd06abSTim J. Robbins miblen = 4; 2772c801d3dSTim J. Robbins } else if (tty) { 2781198f21cSPeter Wemm mib[2] = KERN_PROC_TTY; 2791198f21cSPeter Wemm mib[3] = tdev; 280f2dd06abSTim J. Robbins miblen = 4; 2811198f21cSPeter Wemm } 2821198f21cSPeter Wemm 2831198f21cSPeter Wemm st = sysctl(mib, miblen, NULL, &size, NULL, 0); 2841198f21cSPeter Wemm do { 2851198f21cSPeter Wemm size += size / 10; 2861198f21cSPeter Wemm newprocs = realloc(procs, size); 2871198f21cSPeter Wemm if (newprocs == 0) { 2881198f21cSPeter Wemm if (procs) 2891198f21cSPeter Wemm free(procs); 2901198f21cSPeter Wemm errx(1, "could not reallocate memory"); 2911198f21cSPeter Wemm } 2921198f21cSPeter Wemm procs = newprocs; 2931198f21cSPeter Wemm st = sysctl(mib, miblen, procs, &size, NULL, 0); 2941198f21cSPeter Wemm } while (st == -1 && errno == ENOMEM); 2951198f21cSPeter Wemm if (st == -1) 2961198f21cSPeter Wemm err(1, "could not sysctl(KERN_PROC)"); 2971198f21cSPeter Wemm if (size % sizeof(struct kinfo_proc) != 0) { 2981198f21cSPeter Wemm fprintf(stderr, "proc size mismatch (%d total, %d chunks)\n", 2991198f21cSPeter Wemm size, sizeof(struct kinfo_proc)); 3001198f21cSPeter Wemm fprintf(stderr, "userland out of sync with kernel, recompile libkvm etc\n"); 3011198f21cSPeter Wemm exit(1); 3021198f21cSPeter Wemm } 3031198f21cSPeter Wemm nprocs = size / sizeof(struct kinfo_proc); 3041198f21cSPeter Wemm if (dflag) 3051198f21cSPeter Wemm printf("nprocs %d\n", nprocs); 3061198f21cSPeter Wemm 3071198f21cSPeter Wemm for (i = 0; i < nprocs; i++) { 308a2fefc8dSDag-Erling Smørgrav if ((procs[i].ki_stat & SZOMB) == SZOMB && !zflag) 309a2fefc8dSDag-Erling Smørgrav continue; 31093480bceSJohn Baldwin thispid = procs[i].ki_pid; 31193480bceSJohn Baldwin strncpy(thiscmd, procs[i].ki_comm, MAXCOMLEN); 3121198f21cSPeter Wemm thiscmd[MAXCOMLEN] = '\0'; 31393480bceSJohn Baldwin thistdev = procs[i].ki_tdev; 31493480bceSJohn Baldwin thisuid = procs[i].ki_ruid; /* real uid */ 3151198f21cSPeter Wemm 3161198f21cSPeter Wemm matched = 1; 3171198f21cSPeter Wemm if (user) { 3181198f21cSPeter Wemm if (thisuid != uid) 3191198f21cSPeter Wemm matched = 0; 3201198f21cSPeter Wemm } 3211198f21cSPeter Wemm if (tty) { 3221198f21cSPeter Wemm if (thistdev != tdev) 3231198f21cSPeter Wemm matched = 0; 3241198f21cSPeter Wemm } 3251198f21cSPeter Wemm if (cmd) { 3261198f21cSPeter Wemm if (mflag) { 3271198f21cSPeter Wemm if (regcomp(&rgx, cmd, 3281198f21cSPeter Wemm REG_EXTENDED|REG_NOSUB) != 0) { 3291198f21cSPeter Wemm mflag = 0; 3301198f21cSPeter Wemm warnx("%s: illegal regexp", cmd); 3311198f21cSPeter Wemm } 3321198f21cSPeter Wemm } 3331198f21cSPeter Wemm if (mflag) { 3341198f21cSPeter Wemm pmatch.rm_so = 0; 3351198f21cSPeter Wemm pmatch.rm_eo = strlen(thiscmd); 3361198f21cSPeter Wemm if (regexec(&rgx, thiscmd, 0, &pmatch, 3371198f21cSPeter Wemm REG_STARTEND) != 0) 3381198f21cSPeter Wemm matched = 0; 3391198f21cSPeter Wemm regfree(&rgx); 3401198f21cSPeter Wemm } else { 34169179c14SPeter Wemm if (strncmp(thiscmd, cmd, MAXCOMLEN) != 0) 3421198f21cSPeter Wemm matched = 0; 3431198f21cSPeter Wemm } 3441198f21cSPeter Wemm } 345ebf5d9bcSMike Barcroft if (jflag && thispid == getpid()) 346ebf5d9bcSMike Barcroft matched = 0; 3471198f21cSPeter Wemm if (matched == 0) 3481198f21cSPeter Wemm continue; 3496e1dea06SAndrey A. Chernov if (ac > 0) 3501198f21cSPeter Wemm matched = 0; 3511198f21cSPeter Wemm for (j = 0; j < ac; j++) { 3521198f21cSPeter Wemm if (mflag) { 3531198f21cSPeter Wemm if (regcomp(&rgx, av[j], 3541198f21cSPeter Wemm REG_EXTENDED|REG_NOSUB) != 0) { 3551198f21cSPeter Wemm mflag = 0; 3561198f21cSPeter Wemm warnx("%s: illegal regexp", av[j]); 3571198f21cSPeter Wemm } 3581198f21cSPeter Wemm } 3591198f21cSPeter Wemm if (mflag) { 3601198f21cSPeter Wemm pmatch.rm_so = 0; 3611198f21cSPeter Wemm pmatch.rm_eo = strlen(thiscmd); 3621198f21cSPeter Wemm if (regexec(&rgx, thiscmd, 0, &pmatch, 3631198f21cSPeter Wemm REG_STARTEND) == 0) 3641198f21cSPeter Wemm matched = 1; 3651198f21cSPeter Wemm regfree(&rgx); 3661198f21cSPeter Wemm } else { 3671198f21cSPeter Wemm if (strcmp(thiscmd, av[j]) == 0) 3681198f21cSPeter Wemm matched = 1; 3691198f21cSPeter Wemm } 3701198f21cSPeter Wemm if (matched) 3711198f21cSPeter Wemm break; 3721198f21cSPeter Wemm } 3731198f21cSPeter Wemm if (matched == 0) 3741198f21cSPeter Wemm continue; 3751198f21cSPeter Wemm if (dflag) 3761198f21cSPeter Wemm printf("sig:%d, cmd:%s, pid:%d, dev:0x%x uid:%d\n", sig, 3771198f21cSPeter Wemm thiscmd, thispid, thistdev, thisuid); 3781198f21cSPeter Wemm 3791198f21cSPeter Wemm if (vflag || sflag) 3801198f21cSPeter Wemm printf("kill -%s %d\n", upper(sys_signame[sig]), 3811198f21cSPeter Wemm thispid); 3821198f21cSPeter Wemm 3831198f21cSPeter Wemm killed++; 3841198f21cSPeter Wemm if (!dflag && !sflag) { 3851198f21cSPeter Wemm if (kill(thispid, sig) < 0 /* && errno != ESRCH */ ) { 386a79a73abSDima Dorfman warn("warning: kill -%s %d", 387a79a73abSDima Dorfman upper(sys_signame[sig]), thispid); 3881198f21cSPeter Wemm errors = 1; 3891198f21cSPeter Wemm } 3901198f21cSPeter Wemm } 3911198f21cSPeter Wemm } 3921198f21cSPeter Wemm if (killed == 0) { 3931198f21cSPeter Wemm fprintf(stderr, "No matching processes %swere found\n", 3941198f21cSPeter Wemm getuid() != 0 ? "belonging to you " : ""); 3951198f21cSPeter Wemm errors = 1; 3961198f21cSPeter Wemm } 3971198f21cSPeter Wemm exit(errors); 3981198f21cSPeter Wemm } 399