?? skill.c
字號:
/* * Copyright 1998-2002 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>#include "proc/pwcache.h"#include "proc/sig.h"#include "proc/devname.h"#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */#include "proc/version.h" /* procps_version */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 uid_t *uids;static const 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 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/********************************************************************/static void display_kill_version(void){ switch(program) { case PROG_KILL: fprintf(stdout, "kill (%s)\n",procps_version); return; case PROG_SKILL: fprintf(stdout, "skill (%s)\n",procps_version); return; case PROG_SNICE: fprintf(stdout, "snice (%s)\n",procps_version); return; default: fprintf(stdout, "unknown (%s)\n",procps_version); return; }}/***** kill or nice a process */static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd){ int failed; int saved_errno; char dn_buf[1000]; dev_to_tty(dn_buf, 999, tty, pid, ABBREV_DEV); if(i_flag){ char buf[8]; fprintf(stderr, "%-8s %-8s %5d %-16.16s ? ", (char*)dn_buf,user_from_uid(uid),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, "%-8s %-8s %5d %-16.16s ", (char*)dn_buf,user_from_uid(uid),pid,cmd ); errno = saved_errno; perror(""); return; } if(i_flag) return; if(v_flag){ printf("%-8s %-8s %5d %-16.16s\n", (char*)dn_buf,user_from_uid(uid),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){ int pid; DIR *d; struct dirent *de; if(pids){ pid = pid_count; while(pid--) check_proc(pids[pid]); return; }#if 0 /* could setuid() and kill -1 to have the kernel wipe out a user */ if(!ttys && !cmds && !pids && !i_flag){ }#endif d = opendir("/proc"); if(!d){ perror("/proc"); exit(1); } while(( de = readdir(d) )){ if(de->d_name[0] > '9') continue; if(de->d_name[0] < '1') continue; pid = atoi(de->d_name); if(pid) check_proc(pid); } closedir (d);}/***** kill help */static void kill_usage(void) NORETURN;static void kill_usage(void){ fprintf(stderr, "Usage:\n" " kill pid ... Send SIGTERM to every process listed.\n" " kill signal pid ... Send a signal to every process listed.\n" " kill -s signal pid ... Send a signal to every process listed.\n" " kill -l List all signal names.\n" " kill -L List all signal names in a nice table.\n" " kill -l signal Convert between signal numbers and names.\n" ); exit(1);}/***** kill */static void kill_main(int argc, const char *restrict const *restrict argv) NORETURN;static void kill_main(int argc, const char *restrict const *restrict argv){ const char *sigptr; int signo = SIGTERM; int exitvalue = 0; if(argc<2) kill_usage(); if(!strcmp(argv[1],"-V")|| !strcmp(argv[1],"--version")){ display_kill_version(); exit(0); } if(argv[1][0]!='-'){ argv++; argc--; goto no_more_args; } /* The -l option prints out signal names. */ if(argv[1][1]=='l' && argv[1][2]=='\0'){ if(argc==2){ unix_print_signals(); exit(0); } /* at this point, argc must be 3 or more */ if(argc>128 || argv[2][0] == '-') kill_usage(); exit(print_given_signals(argc-2, argv+2, 80)); } /* The -L option prints out signal names in a nice table. */ if(argv[1][1]=='L' && argv[1][2]=='\0'){ if(argc==2){ pretty_print_signals(); exit(0); } kill_usage(); } if(argv[1][1]=='-' && argv[1][2]=='\0'){ argv+=2; argc-=2; goto no_more_args; } if(argv[1][1]=='-') kill_usage(); /* likely --help */ // FIXME: "kill -sWINCH $$" not handled
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -