home *** CD-ROM | disk | FTP | other *** search
- /* killall.c - kill processes by name. Written by Werner Almesberger */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <dirent.h>
- #include <signal.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <linux/sched.h>
- #include "signals.h"
-
-
- #define COMM_LEN sizeof(dummy.comm)
- #define PROC_BASE "/proc"
- #define MAX_NAMES (sizeof(unsigned long)*8)
-
-
- static struct task_struct dummy;
- static int verbose = 0,interactive = 0;
-
-
- static int ask(char *name,pid_t pid)
- {
- int ch,c;
-
- do {
- printf("Kill %s(%d) ? (y/n) ",name,pid);
- fflush(stdout);
- do if ((ch = getchar()) == EOF) exit(0);
- while (ch == '\n' || ch == '\t' || ch == ' ');
- do if ((c = getchar()) == EOF) exit(0);
- while (c != '\n');
- }
- while (ch != 'y' && ch != 'n' && ch != 'Y' && ch != 'N');
- return ch == 'y' || ch == 'Y';
- }
-
-
- static int kill_all(int signal,int names,char **namelist)
- {
- DIR *dir;
- struct dirent *de;
- FILE *file;
- struct stat st,sts[MAX_NAMES];
- char path[PATH_MAX+1],comm[COMM_LEN+1];
- pid_t pid,self;
- int empty,dummy,i;
- unsigned long found;
-
- for (i = 0; i < names; i++)
- if (!strchr(namelist[i],'/')) sts[i].st_dev = 0;
- else if (stat(namelist[i],&sts[i]) < 0) {
- perror(namelist[i]);
- exit(1);
- }
- self = getpid();
- found = 0;
- if (!(dir = opendir(PROC_BASE))) {
- perror(PROC_BASE);
- exit(1);
- }
- empty = 1;
- while (de = readdir(dir))
- if ((pid = atoi(de->d_name)) && pid != self) {
- sprintf(path,"%s/%d/stat",PROC_BASE,pid);
- if (file = fopen(path,"r")) {
- empty = 0;
- if (fscanf(file,"%d (%[^)]",&dummy,comm) == 2)
- for (i = 0; i < names; i++) {
- if (!sts[i].st_dev) {
- if (strcmp(namelist[i],comm)) continue;
- }
- else {
- sprintf(path,"%s/%d/exe",PROC_BASE,pid);
- if (stat(path,&st) < 0) continue;
- if (sts[i].st_dev != st.st_dev || sts[i].st_ino !=
- st.st_ino) continue;
- }
- if (interactive && !ask(comm,pid)) continue;
- if (kill(pid,signal) >= 0) {
- if (verbose)
- fprintf(stderr,"Killed %s(%d)\n",comm,pid);
- found |= 1 << i;
- }
- else if (errno != ESRCH || interactive)
- fprintf(stderr,"%s(%d): %s\n",comm,pid,
- strerror(errno));
- }
- (void) fclose(file);
- }
- }
- (void) closedir(dir);
- if (empty) {
- fprintf(stderr,PROC_BASE " is empty (not mounted ?)\n");
- exit(1);
- }
- for (i = 0; i < names; i++)
- if (!(found & (1 << i)))
- fprintf(stderr,"%s: no process killed\n",namelist[i]);
- return found == ((1 << (names-1)) | ((1 << (names-1))-1)) ? 0 : 1;
- }
-
-
- static void usage(void)
- {
- fprintf(stderr,"usage: killall [ -iv ] [ -signal ] name ...\n");
- fprintf(stderr," killall -l\n\n");
- fprintf(stderr," -i ask for confirmation before killing\n");
- fprintf(stderr," -l list all known signal names\n");
- fprintf(stderr," -signal send signal instead of SIGTERM\n");
- fprintf(stderr," -v report if the signal was successfully sent\n\n"
- );
- exit(1);
- }
-
-
- int main(int argc,char **argv)
- {
- int sig_num;
-
- if (argc == 2 && !strcmp(argv[1],"-l")) {
- list_signals();
- return 0;
- }
- sig_num = SIGTERM;
- while (argc > 1 && *argv[1] == '-') {
- argc--;
- argv++;
- if (!strcmp(*argv,"-v")) verbose = 1;
- else if (!strcmp(*argv,"-i")) interactive = 1;
- else if (!strcmp(*argv,"-vi") || !strcmp(*argv,"-iv"))
- verbose = interactive = 1;
- else sig_num = get_signal(*argv+1,"killall");
- }
- if (argc < 2) usage();
- if (argc > MAX_NAMES+1) {
- fprintf(stderr,"Maximum number of names is %d\n",MAX_NAMES);
- exit(1);
- }
- return kill_all(sig_num,argc-1,argv+1);
- }
-