📄 skill.c
字号:
/* * Copyright 1998 by Albert Cahalan; all rights resered. * This file may be used subject to the terms and conditions of the * GNU Library General Public License Version 2, or any later version * at your option, as published by the Free Software Foundation. * 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 Library General Public License for more details. */#include <fcntl.h>#include <pwd.h>#include <dirent.h>#include <errno.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/resource.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>static int f_flag, i_flag, v_flag, w_flag, n_flag;static int tty_count, uid_count, cmd_count, pid_count;static int *ttys;static int *uids;static char **cmds;static int *pids;#define ENLIST(thing,addme) do{ \if(!thing##s) thing##s = malloc(sizeof(*thing##s)*saved_argc); \if(!thing##s) fprintf(stderr,"No memory.\n"),exit(2); \thing##s[thing##_count++] = addme; \}while(0)static int my_pid;static int saved_argc;static char **saved_argv;static int sig_or_pri;static int program;#define PROG_GARBAGE 0 /* keep this 0 */#define PROG_KILL 1#define PROG_SKILL 2/* #define PROG_NICE 3 */ /* easy, but the old one isn't broken */#define PROG_SNICE 4/***********************************************************************//* Linux signals: * * SIGSYS is required by Unix98. * SIGEMT is part of SysV, BSD, and ancient UNIX tradition. * * They are provided by these Linux ports: alpha, mips, sparc, and sparc64. * You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm. * (this is a Linux & libc bug -- both must be fixed) * * Total garbage: SIGIO SIGINFO SIGIOT SIGLOST SIGCLD * Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots) */#ifdef SIGSYS# undef SIGUNUSED# undef SIGSTKFLT#endif#ifndef SIGRTMIN# define SIGRTMIN 32#endifint sigvals[] = {SIGABRT,SIGALRM,SIGBUS,SIGCHLD,SIGCONT,#ifdef SIGEMTSIGEMT,#endifSIGFPE,SIGHUP,SIGILL,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,#ifdef SIGPWRSIGPWR,#endifSIGQUIT,SIGSEGV,#ifdef SIGSTKFLTSIGSTKFLT,#endifSIGSTOP,#ifdef SIGSYSSIGSYS,#endifSIGTERM,SIGTRAP,SIGTSTP,SIGTTIN,SIGTTOU,#ifdef SIGUNUSEDSIGUNUSED,#endifSIGURG,SIGUSR1,SIGUSR2,SIGVTALRM,SIGWINCH,SIGXCPU,SIGXFSZ,};char *signames[] = {"ABRT","ALRM","BUS","CHLD","CONT",#ifdef SIGEMT"EMT",#endif"FPE","HUP","ILL","INT","KILL","PIPE","POLL","PROF","PWR","QUIT","SEGV",#ifdef SIGSTKFLT"STKFLT",#endif"STOP",#ifdef SIGSYS"SYS",#endif"TERM","TRAP","TSTP","TTIN","TTOU",#ifdef SIGUNUSED"UNUSED",#endif"URG","USR1","USR2","VTALRM","WINCH","XCPU","XFSZ"};const int number_of_signals = sizeof(sigvals)/sizeof(int);static int compare_signal_names(const void *a, const void *b){ return strcasecmp(*(char**)a,*(char**)b);}static int signal_name_to_number(char *name){ const char **ptr; if(!strncasecmp(name,"SIG",3)) name += 3; ptr = bsearch(&name, signames, number_of_signals, sizeof(char *), compare_signal_names ); if(!ptr){ long val; char *endp; val = strtol(name,&endp,10); if(*endp) return -1; /* not valid */ if(val>127) return -1; /* not valid */ return val; } return sigvals[((unsigned long)ptr-(unsigned long)signames)/sizeof(char *)];}static const char *signal_name(int signo){ static char buf[32]; int n = number_of_signals; signo &= 0x7f; /* need to process exit values too */ while(n--){ if(sigvals[n]==signo) return signames[n]; } if(signo) sprintf(buf, "RTMIN+%d", signo-SIGRTMIN); else strcpy(buf,"0"); /* AIX would use "NULL" */ return buf;}static void pretty_print_signals(void){ int i = 0; while(++i <= number_of_signals){ int n; n = printf("%2d %s", i, signal_name(i)); if(i%7) printf(" \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n); else printf("\n"); } if((i-1)%7) printf("\n");}static void unix_print_signals(void){ int pos = 0; int i = 0; while(++i <= number_of_signals){ if(i-1) printf("%c", (pos>73)?(pos=0,'\n'):(pos++,' ') ); pos += printf("%s", signal_name(i)); } printf("\n");}/********************************************************************//* This is junk of course, to be replaced soon */const char *uid_to_user(int uid){ static struct passwd *p; static char txt[64]; p = getpwuid(uid); if(p) return p->pw_name; sprintf(txt, "%d", uid); return txt;}/* this must be replaced soon... */const char *dev_to_tty(int tty){ static char txt[64]; sprintf(txt, "%d,%d", (tty>>8)&0xff, tty&0xff); return txt;}/********************************************************************//***** kill or nice a process */static void hurt_proc(int tty, int user, int pid, char *cmd){ int failed; int saved_errno; if(i_flag){ char buf[8]; fprintf(stderr, "%-8.8s %-8.8s %5d %-16.16s ? ", dev_to_tty(tty),uid_to_user(user),pid,cmd ); if(!fgets(buf,7,stdin)){ printf("\n"); exit(0); } if(*buf!='y' && *buf!='Y') return; } /* do the actual work */ if(program==PROG_SKILL) failed=kill(pid,sig_or_pri); else failed=setpriority(PRIO_PROCESS,pid,sig_or_pri); saved_errno = errno; if(w_flag && failed){ fprintf(stderr, "%-8.8s %-8.8s %5d %-16.16s ", dev_to_tty(tty),uid_to_user(user),pid,cmd ); errno = saved_errno; perror(""); return; } if(i_flag) return; if(v_flag){ printf("%-8.8s %-8.8s %5d %-16.16s\n", dev_to_tty(tty),uid_to_user(user),pid,cmd ); return; } if(n_flag){ printf("%d\n",pid); return; }}/***** check one process */static void check_proc(int pid){ char buf[128]; struct stat statbuf; char *tmp; int tty; int fd; int i; if(pid==my_pid) return; sprintf(buf, "/proc/%d/stat", pid); /* pid (cmd) state ppid pgrp session tty */ fd = open(buf,O_RDONLY); if(fd==-1){ /* process exited maybe */ if(pids && w_flag) printf("WARNING: process %d could not be found.",pid); return; } fstat(fd, &statbuf); if(uids){ /* check the EUID */ i=uid_count; while(i--) if(uids[i]==statbuf.st_uid) break; if(i==-1) goto closure; } read(fd,buf,128); buf[127] = '\0'; tmp = strrchr(buf, ')'); *tmp++ = '\0'; i = 5; while(i--) while(*tmp++!=' '); /* scan to find tty */ tty = atoi(tmp); if(ttys){ i=tty_count; while(i--) if(ttys[i]==tty) break; if(i==-1) goto closure; } tmp = strchr(buf, '(') + 1; if(cmds){ i=cmd_count; /* fast comparison trick -- useful? */ while(i--) if(cmds[i][0]==*tmp && !strcmp(cmds[i],tmp)) break; if(i==-1) goto closure; } /* This is where we kill/nice something. *//* fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n", pid, statbuf.st_uid, tty>>8, tty&0xf, tmp );*/ hurt_proc(tty, statbuf.st_uid, pid, tmp);closure: close(fd); /* kill/nice _first_ to avoid PID reuse */}/***** debug function */#if 0static void show_lists(void){ int i; fprintf(stderr, "%d TTY: ", tty_count); if(ttys){ i=tty_count; while(i--){ fprintf(stderr, "%d,%d%c", (ttys[i]>>8)&0xff, ttys[i]&0xff, i?' ':'\n'); } }else fprintf(stderr, "\n"); fprintf(stderr, "%d UID: ", uid_count); if(uids){ i=uid_count; while(i--) fprintf(stderr, "%d%c", uids[i], i?' ':'\n'); }else fprintf(stderr, "\n"); fprintf(stderr, "%d PID: ", pid_count); if(pids){ i=pid_count; while(i--) fprintf(stderr, "%d%c", pids[i], i?' ':'\n'); }else fprintf(stderr, "\n"); fprintf(stderr, "%d CMD: ", cmd_count); if(cmds){ i=cmd_count; while(i--) fprintf(stderr, "%s%c", cmds[i], i?' ':'\n'); }else fprintf(stderr, "\n");}#endif/***** iterate over all PIDs */static void iterate(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -