#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 */
+#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 program = -1;
#define PROG_KILL 1
#define PROG_SKILL 2
-/* #define PROG_NICE 3 */ /* easy, but the old one isn't broken */
+/*#define PROG_NICE 3*/ /* easy, but the old one isn't broken */
#define PROG_SNICE 4
+static void display_kill_version(void)
+{
+ fprintf(stdout, PROCPS_NG_VERSION);
+}
-/********************************************************************/
-
-static void display_kill_version(void){
- fprintf(stdout, PROCPS_NG_VERSION);
+/* 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;
+ }
}
-/***** 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;
+ /* pid (cmd) state ppid pgrp session tty */
+ sprintf(buf, "/proc/%d/stat", pid);
+ fd = open(buf, O_RDONLY);
+ if (fd == -1) {
+ /* process exited maybe */
+ if (pids && w_flag)
+ printf(_("WARNING: process %d could not be found.\n"),
+ 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. */
+ /* for debugging purposes?
+ 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:
+ /* kill/nice _first_ to avoid PID reuse */
+ close(fd);
}
+/* debug function */
+#if 0
+static void show_lists(void)
+{
+ int i;
-/***** 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.\n"),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 */
-}
+ 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");
-/***** debug function */
-#if 0
-static void show_lists(void){
- int i;
+ 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 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");
+ 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;
- }
+/* 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){
- }
+ /* 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);
+ 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 */
+/* kill help */
static void __attribute__ ((__noreturn__)) kill_usage(void)
{
fputs(USAGE_HEADER, stderr);
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;
- }
+/* 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. */
+ 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
- if(argv[1][2]=='\0' && (argv[1][1]=='s' || argv[1][1]=='n')){
- sigptr = argv[2];
- argv+=3;
- argc-=3;
- }else{
- sigptr = argv[1]+1;
- argv+=2;
- argc-=2;
- }
- signo = signal_name_to_number(sigptr);
- if(signo<0){
- fprintf(stderr, _("ERROR: unknown signal name \"%s\".\n"), sigptr);
- kill_usage();
- }
-no_more_args:
- if(!argc) kill_usage(); /* nothing to kill? */
- while(argc--){
- long pid;
- char *endp;
- pid = strtol(argv[argc],&endp,10);
- if(!*endp && (endp != argv[argc])){
- if(!kill((pid_t)pid,signo)) continue;
- // The UNIX standard contradicts itself. If at least one process
- // is matched for each PID (as if processes could share PID!) and
- // "the specified signal was successfully processed" (the systcall
- // returned zero?) for at least one of those processes, then we must
- // exit with zero. Note that an error might have also occured.
- // The standard says we return non-zero if an error occurs. Thus if
- // killing two processes gives 0 for one and EPERM for the other,
- // we are required to return both zero and non-zero. Quantum kill???
- perror("kill");
- exitvalue = 1;
- continue;
- }
- fprintf(stderr, _("ERROR: garbage process ID \"%s\".\n"), argv[argc]);
- kill_usage();
- }
- exit(exitvalue);
+ /* 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
+ if (argv[1][2] == '\0' && (argv[1][1] == 's' || argv[1][1] == 'n')) {
+ sigptr = argv[2];
+ argv += 3;
+ argc -= 3;
+ } else {
+ sigptr = argv[1] + 1;
+ argv += 2;
+ argc -= 2;
+ }
+ signo = signal_name_to_number(sigptr);
+ if (signo < 0) {
+ fprintf(stderr, _("ERROR: unknown signal name \"%s\".\n"),
+ sigptr);
+ kill_usage();
+ }
+ no_more_args:
+ if (!argc)
+ kill_usage(); /* nothing to kill? */
+ while (argc--) {
+ long pid;
+ char *endp;
+ pid = strtol(argv[argc], &endp, 10);
+ if (!*endp && (endp != argv[argc])) {
+ if (!kill((pid_t) pid, signo))
+ continue;
+ /*
+ * The UNIX standard contradicts itself. If at least
+ * one process is matched for each PID (as if
+ * processes could share PID!) and "the specified
+ * signal was successfully processed" (the systcall
+ * returned zero?) for at least one of those
+ * processes, then we must exit with zero. Note that
+ * an error might have also occured. The standard
+ * says we return non-zero if an error occurs. Thus
+ * if killing two processes gives 0 for one and EPERM
+ * for the other, we are required to return both zero
+ * and non-zero. Quantum kill???
+ */
+ perror("kill");
+ exitvalue = 1;
+ continue;
+ }
+ fprintf(stderr, _("ERROR: garbage process ID \"%s\".\n"),
+ argv[argc]);
+ kill_usage();
+ }
+ exit(exitvalue);
}
-/***** skill/snice help */
+/* skill/snice help */
static void __attribute__ ((__noreturn__)) skillsnice_usage(void)
{
- fputs(USAGE_HEADER, stderr);
+ fputs(USAGE_HEADER, stderr);
if (program == PROG_SKILL) {
fprintf(stderr,
" %s [signal] [options] <expression>\n",
fputs(_(" -f fast mode (not implemented)\n"), stderr);
fputs(_(" -i interactive\n"), stderr);
fputs(_(" -l list all signal names\n"), stderr);
- fputs(_(" -L list all signal names in a nice table\n"), stderr);
+ fputs(_(" -L list all signal names in a nice table\n"),
+ stderr);
fputs(_(" -n no action\n"), stderr);
fputs(_(" -v explain what is being done\n"), stderr);
fputs(_(" -w enable warnings (not implemented)\n"), stderr);
fputs(USAGE_VERSION, stderr);
fputs(_("\n"), stderr);
fputs(_("Expression can be: terminal, user, pid, command.\n"), stderr);
- fputs(_("The options below may be used to ensure correct interpretation.\n"), stderr);
+ fputs(_
+ ("The options below may be used to ensure correct interpretation.\n"),
+ stderr);
fputs(_(" -c <command> expression is a command name\n"), stderr);
fputs(_(" -p <pid> expression is a process id number\n"), stderr);
fputs(_(" -t <tty> expression is a terminal\n"), stderr);
"The default signal is TERM. Use -l or -L to list available signals.\n"
"Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.\n"
"Alternate signals may be specified in three ways: -SIGKILL -KILL -9\n"));
- fprintf(stderr, USAGE_MAN_TAIL("skill(1)"));
+ fprintf(stderr, USAGE_MAN_TAIL("skill(1)"));
} else {
fprintf(stderr,
_("\n"
"The default priority is +4. (snice +4 ...)\n"
"Priority numbers range from +20 (slowest) to -20 (fastest).\n"
"Negative priority numbers are restricted to administrative users.\n"));
- fprintf(stderr, USAGE_MAN_TAIL("snice(1)"));
+ fprintf(stderr, USAGE_MAN_TAIL("snice(1)"));
}
exit(1);
}
#if 0
-static void _skillsnice_usage(int line){
- fprintf(stderr,_("Something at line %d.\n"), line);
- skillsnice_usage();
+static void _skillsnice_usage(int line)
+{
+ fprintf(stderr, _("Something at line %d.\n"), line);
+ skillsnice_usage();
}
+
#define skillsnice_usage() _skillsnice_usage(__LINE__)
#endif
#define NEXTARG (argc?( argc--, ((argptr=*++argv)) ):NULL)
-/***** common skill/snice argument parsing code */
+/* common skill/snice argument parsing code */
#define NO_PRI_VAL ((int)0xdeafbeef)
-static void skillsnice_parse(int argc, const char *restrict const *restrict argv){
- int signo = -1;
- int prino = NO_PRI_VAL;
- int force = 0;
- int num_found = 0;
- const char *restrict argptr;
- if(argc<2) skillsnice_usage();
- if(argc==2 && argv[1][0]=='-'){
- if(!strcmp(argv[1],"-L")){
- pretty_print_signals();
- exit(0);
- }
- if(!strcmp(argv[1],"-l")){
- unix_print_signals();
- exit(0);
- }
- if(!strcmp(argv[1],"-V")|| !strcmp(argv[1],"--version")){
- display_kill_version();
- exit(0);
- }
- skillsnice_usage();
- }
- NEXTARG;
- /* Time for serious parsing. What does "skill -int 123 456" mean? */
- while(argc){
- if(force && !num_found){ /* if forced, _must_ find something */
- fprintf(stderr,_("ERROR: -%c used with bad data.\n"), force);
- skillsnice_usage();
- }
- force = 0;
- if(program==PROG_SKILL && signo<0 && *argptr=='-'){
- signo = signal_name_to_number(argptr+1);
- if(signo>=0){ /* found a signal */
- if(!NEXTARG) break;
- continue;
- }
- }
- if(program==PROG_SNICE && prino==NO_PRI_VAL
- && (*argptr=='+' || *argptr=='-') && argptr[1]){
- long val;
- char *endp;
- val = strtol(argptr,&endp,10);
- if(!*endp && val<=999 && val>=-999){
- prino=val;
- if(!NEXTARG) break;
- continue;
- }
- }
- /* If '-' found, collect any flags. (but lone "-" is a tty) */
- if(*argptr=='-' && argptr[1]){
- argptr++;
- do{
- switch(( force = *argptr++ )){
- default: skillsnice_usage();
- case 't':
- case 'u':
- case 'p':
- case 'c':
- if(!*argptr){ /* nothing left here, *argptr is '\0' */
- if(!NEXTARG){
- fprintf(stderr,_("ERROR: -%c with nothing after it.\n"), force);
- skillsnice_usage();
- }
- }
- goto selection_collection;
- case 'f': f_flag++; break;
- case 'i': i_flag++; break;
- case 'v': v_flag++; break;
- case 'w': w_flag++; break;
- case 'n': n_flag++; break;
- case 0:
- NEXTARG;
- /*
- * If no more arguments, all the "if(argc)..." tests will fail
- * and the big loop will exit.
- */
- } /* END OF SWITCH */
- }while(force);
- } /* END OF IF */
-selection_collection:
- num_found = 0; /* we should find at least one thing */
- switch(force){ /* fall through each data type */
- default: skillsnice_usage();
- case 0: /* not forced */
- if (argptr && argptr[0] == '-') /* its the next argument not a parameter */
- continue;
- case 't':
- if(argc){
- struct stat sbuf;
- char path[32];
- if(!argptr) skillsnice_usage(); /* Huh? Maybe "skill -t ''". */
- snprintf(path,32,"/dev/%s",argptr);
- if(stat(path, &sbuf)>=0 && S_ISCHR(sbuf.st_mode)){
- num_found++;
- ENLIST(tty,sbuf.st_rdev);
- if(!NEXTARG) break;
- }else if(!(argptr[1])){ /* if only 1 character */
- switch(*argptr){
- default:
- if(stat(argptr,&sbuf)<0) break; /* the shell eats '?' */
- case '-':
- case '?':
- num_found++;
- ENLIST(tty,0);
- if(!NEXTARG) break;
- }
- }
- }
- if(force) continue;
- case 'u':
- if(argc){
- struct passwd *passwd_data;
- passwd_data = getpwnam(argptr);
- if(passwd_data){
- num_found++;
- ENLIST(uid,passwd_data->pw_uid);
- if(!NEXTARG) break;
- }
- }
- if(force) continue;
- case 'p':
- if(argc && *argptr>='0' && *argptr<='9'){
- char *endp;
- int num;
- num = strtol(argptr, &endp, 0);
- if(*endp == '\0'){
- num_found++;
- ENLIST(pid,num);
- if(!NEXTARG) break;
- }
- }
- if(force) continue;
- if(num_found) continue; /* could still be an option */
- case 'c':
- if(argc){
- num_found++;
- ENLIST(cmd,argptr);
- if(!NEXTARG) break;
- }
- } /* END OF SWITCH */
- } /* END OF WHILE */
- /* No more arguments to process. Must sanity check. */
- if(!tty_count && !uid_count && !cmd_count && !pid_count){
- fprintf(stderr,_("ERROR: no process selection criteria.\n"));
- skillsnice_usage();
- }
- if((f_flag|i_flag|v_flag|w_flag|n_flag) & ~1){
- fprintf(stderr,_("ERROR: general flags may not be repeated.\n"));
- skillsnice_usage();
- }
- if(i_flag && (v_flag|f_flag|n_flag)){
- fprintf(stderr,_("ERROR: -i makes no sense with -v, -f, and -n.\n"));
- skillsnice_usage();
- }
- if(v_flag && (i_flag|f_flag)){
- fprintf(stderr,_("ERROR: -v makes no sense with -i and -f.\n"));
- skillsnice_usage();
- }
- /* OK, set up defaults */
- if(prino==NO_PRI_VAL) prino=4;
- if(signo<0) signo=SIGTERM;
- if(n_flag){
- program=PROG_SKILL;
- signo=0; /* harmless */
- }
- if(program==PROG_SKILL) sig_or_pri = signo;
- else sig_or_pri = prino;
+static void skillsnice_parse(int argc,
+ const char *restrict const *restrict argv)
+{
+ int signo = -1;
+ int prino = NO_PRI_VAL;
+ int force = 0;
+ int num_found = 0;
+ const char *restrict argptr;
+ if (argc < 2)
+ skillsnice_usage();
+ if (argc == 2 && argv[1][0] == '-') {
+ if (!strcmp(argv[1], "-L")) {
+ pretty_print_signals();
+ exit(0);
+ }
+ if (!strcmp(argv[1], "-l")) {
+ unix_print_signals();
+ exit(0);
+ }
+ if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
+ display_kill_version();
+ exit(0);
+ }
+ skillsnice_usage();
+ }
+ NEXTARG;
+ /* Time for serious parsing. What does "skill -int 123 456" mean? */
+ while (argc) {
+ if (force && !num_found) {
+ /* if forced, _must_ find something */
+ fprintf(stderr, _("ERROR: -%c used with bad data.\n"),
+ force);
+ skillsnice_usage();
+ }
+ force = 0;
+ if (program == PROG_SKILL && signo < 0 && *argptr == '-') {
+ signo = signal_name_to_number(argptr + 1);
+ if (signo >= 0) {
+ /* found a signal */
+ if (!NEXTARG)
+ break;
+ continue;
+ }
+ }
+ if (program == PROG_SNICE && prino == NO_PRI_VAL
+ && (*argptr == '+' || *argptr == '-') && argptr[1]) {
+ long val;
+ char *endp;
+ val = strtol(argptr, &endp, 10);
+ if (!*endp && val <= 999 && val >= -999) {
+ prino = val;
+ if (!NEXTARG)
+ break;
+ continue;
+ }
+ }
+ /* If '-' found, collect any flags. (but lone "-" is a tty) */
+ if (*argptr == '-' && argptr[1]) {
+ argptr++;
+ do {
+ switch ((force = *argptr++)) {
+ default:
+ skillsnice_usage();
+ case 't':
+ case 'u':
+ case 'p':
+ case 'c':
+ if (!*argptr) {
+ /* nothing left here, *argptr is '\0' */
+ if (!NEXTARG) {
+ fprintf(stderr,
+ _
+ ("ERROR: -%c with nothing after it.\n"),
+ force);
+ skillsnice_usage();
+ }
+ }
+ goto selection_collection;
+ case 'f':
+ f_flag++;
+ break;
+ case 'i':
+ i_flag++;
+ break;
+ case 'v':
+ v_flag++;
+ break;
+ case 'w':
+ w_flag++;
+ break;
+ case 'n':
+ n_flag++;
+ break;
+ case 0:
+ NEXTARG;
+ /*
+ * If no more arguments, all the
+ * "if(argc)..." tests will fail and
+ * the big loop will exit.
+ */
+ } /* END OF SWITCH */
+ } while (force);
+ } /* END OF IF */
+ selection_collection:
+ num_found = 0; /* we should find at least one thing */
+ switch (force) {
+ /* fall through each data type */
+ default:
+ skillsnice_usage();
+ case 0: /* not forced */
+ if (argptr && argptr[0] == '-')
+ /* its the next argument not a parameter */
+ continue;
+ case 't':
+ if (argc) {
+ struct stat sbuf;
+ char path[32];
+ if (!argptr)
+ /* Huh? Maybe "skill -t ''". */
+ skillsnice_usage();
+ snprintf(path, 32, "/dev/%s", argptr);
+ if (stat(path, &sbuf) >= 0
+ && S_ISCHR(sbuf.st_mode)) {
+ num_found++;
+ ENLIST(tty, sbuf.st_rdev);
+ if (!NEXTARG)
+ break;
+ } else if (!(argptr[1])) {
+ /* if only 1 character */
+ switch (*argptr) {
+ default:
+ if (stat(argptr, &sbuf) < 0)
+ /* the shell eats '?' */
+ break;
+ case '-':
+ case '?':
+ num_found++;
+ ENLIST(tty, 0);
+ if (!NEXTARG)
+ break;
+ }
+ }
+ }
+ if (force)
+ continue;
+ case 'u':
+ if (argc) {
+ struct passwd *passwd_data;
+ passwd_data = getpwnam(argptr);
+ if (passwd_data) {
+ num_found++;
+ ENLIST(uid, passwd_data->pw_uid);
+ if (!NEXTARG)
+ break;
+ }
+ }
+ if (force)
+ continue;
+ case 'p':
+ if (argc && *argptr >= '0' && *argptr <= '9') {
+ char *endp;
+ int num;
+ num = strtol(argptr, &endp, 0);
+ if (*endp == '\0') {
+ num_found++;
+ ENLIST(pid, num);
+ if (!NEXTARG)
+ break;
+ }
+ }
+ if (force)
+ continue;
+ if (num_found)
+ /* could still be an option */
+ continue;
+ case 'c':
+ if (argc) {
+ num_found++;
+ ENLIST(cmd, argptr);
+ if (!NEXTARG)
+ break;
+ }
+ } /* END OF SWITCH */
+ } /* END OF WHILE */
+ /* No more arguments to process. Must sanity check. */
+ if (!tty_count && !uid_count && !cmd_count && !pid_count) {
+ fprintf(stderr, _("ERROR: no process selection criteria.\n"));
+ skillsnice_usage();
+ }
+ if ((f_flag | i_flag | v_flag | w_flag | n_flag) & ~1) {
+ fprintf(stderr,
+ _("ERROR: general flags may not be repeated.\n"));
+ skillsnice_usage();
+ }
+ if (i_flag && (v_flag | f_flag | n_flag)) {
+ fprintf(stderr,
+ _("ERROR: -i makes no sense with -v, -f, and -n.\n"));
+ skillsnice_usage();
+ }
+ if (v_flag && (i_flag | f_flag)) {
+ fprintf(stderr,
+ _("ERROR: -v makes no sense with -i and -f.\n"));
+ skillsnice_usage();
+ }
+ /* OK, set up defaults */
+ if (prino == NO_PRI_VAL)
+ prino = 4;
+ if (signo < 0)
+ signo = SIGTERM;
+ if (n_flag) {
+ program = PROG_SKILL;
+ /* harmless */
+ signo = 0;
+ }
+ if (program == PROG_SKILL)
+ sig_or_pri = signo;
+ else
+ sig_or_pri = prino;
}
-/***** main body */
-int main(int argc, const char *argv[]){
- const char *tmpstr;
- my_pid = getpid();
- saved_argc = argc;
- if(!argc){
- fprintf(stderr,_("ERROR: could not determine own name.\n"));
- exit(1);
- }
- tmpstr=strrchr(*argv,'/');
- if(tmpstr) tmpstr++;
- if(!tmpstr) tmpstr=*argv;
- if(strstr(tmpstr,"kill")) program = PROG_KILL;
- if(strstr(tmpstr,"skill")) program = PROG_SKILL;
- if(strstr(tmpstr,"snice")) program = PROG_SNICE;
- switch(program){
- case PROG_SNICE:
- case PROG_SKILL:
- setpriority(PRIO_PROCESS,my_pid,-20);
- skillsnice_parse(argc, argv);
-/* show_lists(); */
- iterate(); /* this is it, go get them */
- break;
- case PROG_KILL:
- kill_main(argc, argv);
- break;
- default:
- fprintf(stderr,_("ERROR: no \"%s\" support.\n"),tmpstr);
- }
- return 0;
+/* main body */
+int main(int argc, const char *argv[])
+{
+ const char *tmpstr;
+ my_pid = getpid();
+ saved_argc = argc;
+ if (!argc) {
+ fprintf(stderr, _("ERROR: could not determine own name.\n"));
+ exit(1);
+ }
+ tmpstr = strrchr(*argv, '/');
+ if (tmpstr)
+ tmpstr++;
+ if (!tmpstr)
+ tmpstr = *argv;
+ if (strstr(tmpstr, "kill"))
+ program = PROG_KILL;
+ if (strstr(tmpstr, "skill"))
+ program = PROG_SKILL;
+ if (strstr(tmpstr, "snice"))
+ program = PROG_SNICE;
+ switch (program) {
+ case PROG_SNICE:
+ case PROG_SKILL:
+ setpriority(PRIO_PROCESS, my_pid, -20);
+ skillsnice_parse(argc, argv);
+ /* show_lists(); */
+ /* this is it, go get them */
+ iterate();
+ break;
+ case PROG_KILL:
+ kill_main(argc, argv);
+ break;
+ default:
+ fprintf(stderr, _("ERROR: no \"%s\" support.\n"), tmpstr);
+ }
+ return 0;
}
-
-