skill: add long options & new debugging option

Done for skillsnice_parse(), meaning the kill needs functionality
will be done later.

This commit also introduces new debugging option.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2011-10-18 22:41:25 +02:00
parent 61094186fe
commit 991b8a94f0

248
skill.c
View File

@ -9,6 +9,7 @@
* GNU Library General Public License for more details. * GNU Library General Public License for more details.
*/ */
#include <dirent.h> #include <dirent.h>
#include <getopt.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
@ -97,7 +98,7 @@ static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd,
else else
failed = setpriority(PRIO_PROCESS, pid, sig_or_pri); failed = setpriority(PRIO_PROCESS, pid, sig_or_pri);
saved_errno = errno; saved_errno = errno;
if (run_time->warnings && failed) { if ((run_time->warnings && failed) || run_time->debugging) {
fprintf(stderr, "%-8s %-8s %5d %-16.16s ", fprintf(stderr, "%-8s %-8s %5d %-16.16s ",
(char *)dn_buf, user_from_uid(uid), pid, cmd); (char *)dn_buf, user_from_uid(uid), pid, cmd);
errno = saved_errno; errno = saved_errno;
@ -126,7 +127,7 @@ static void check_proc(int pid, struct run_time_conf_t *run_time)
int tty; int tty;
int fd; int fd;
int i; int i;
if (pid == my_pid) if (pid == my_pid || pid == 0)
return; return;
/* pid (cmd) state ppid pgrp session tty */ /* pid (cmd) state ppid pgrp session tty */
sprintf(buf, "/proc/%d/stat", pid); sprintf(buf, "/proc/%d/stat", pid);
@ -191,6 +192,8 @@ static void show_lists(void)
{ {
int i; int i;
fprintf(stderr, _("signal: %d\n"), sig_or_pri);
fprintf(stderr, _("%d TTY: "), tty_count); fprintf(stderr, _("%d TTY: "), tty_count);
if (ttys) { if (ttys) {
i = tty_count; i = tty_count;
@ -481,125 +484,99 @@ int skill_sig_option(int *argc, char **argv)
return signo; return signo;
} }
#define NO_PRI_VAL ((int)0xdeafbeef)
static void skillsnice_parse(int argc, static void skillsnice_parse(int argc,
char ** argv, char **argv, struct run_time_conf_t *run_time)
struct run_time_conf_t *run_time)
{ {
int signo = -1; int signo = -1;
int prino = NO_PRI_VAL; int prino = DEFAULT_NICE;
int force = 0; int force = 0;
int num_found = 0; int num_found = 0;
int ch, i;
const char *restrict argptr; const char *restrict argptr;
static const struct option longopts[] = {
{"command", required_argument, NULL, 'c'},
{"debug", no_argument, NULL, 'd'},
{"fast", no_argument, NULL, 'f'},
{"interactive", no_argument, NULL, 'i'},
{"list", no_argument, NULL, 'l'},
{"no-action", no_argument, NULL, 'n'},
{"pid", required_argument, NULL, 'p'},
{"table", no_argument, NULL, 'L'},
{"tty", required_argument, NULL, 't'},
{"user", required_argument, NULL, 'u'},
{"verbose", no_argument, NULL, 'v'},
{"warnings", no_argument, NULL, 'w'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{NULL, 0, NULL, 0}
};
if (argc < 2) if (argc < 2)
skillsnice_usage(); skillsnice_usage();
sig_or_pri = -1;
if (program == PROG_SNICE) if (program == PROG_SNICE)
prino = snice_prio_option(&argc, argv); prino = snice_prio_option(&argc, argv);
else if (program == PROG_SKILL) else if (program == PROG_SKILL) {
signo = skill_sig_option(&argc, argv); signo = skill_sig_option(&argc, argv);
if (-1 < signo)
sig_or_pri = signo;
}
if (argc == 2 && argv[1][0] == '-') { pid_count = 0;
if (!strcmp(argv[1], "-L")) {
pretty_print_signals(); while ((ch =
exit(0); getopt_long(argc, argv, "c:dfilnp:Lt:u:vwhV", longopts,
} NULL)) != -1)
if (!strcmp(argv[1], "-l")) { switch (ch) {
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 '-' 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': case 'c':
if (!*argptr) { ENLIST(cmd, optarg);
/* nothing left here, *argptr is '\0' */ break;
if (!NEXTARG) { case 'd':
fprintf(stderr, run_time->debugging = 1;
_ break;
("ERROR: -%c with nothing after it.\n"),
force);
skillsnice_usage();
}
}
goto selection_collection;
case 'f': case 'f':
run_time->fast++; run_time->fast = 1;
break; break;
case 'i': case 'i':
run_time->interactive++; run_time->interactive = 1;
break;
case 'v':
run_time->verbose++;
break;
case 'w':
run_time->warnings++;
break; break;
case 'l':
unix_print_signals();
exit(EXIT_SUCCESS);
case 'n': case 'n':
run_time->noaction++; run_time->noaction = 1;
break; break;
case 0: case 'p':
NEXTARG; ENLIST(pid,
/* strtol_or_err(optarg,
* If no more arguments, all the _("failed to parse argument")));
* "if(argc)..." tests will fail and pid_count++;
* the big loop will exit. break;
*/ case 'L':
} /* END OF SWITCH */ pretty_print_signals();
} while (force); exit(EXIT_SUCCESS);
} /* 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': case 't':
if (argc) { {
struct stat sbuf; struct stat sbuf;
char path[32]; char path[32];
if (!argptr) if (!optarg)
/* Huh? Maybe "skill -t ''". */ /* Huh? Maybe "skill -t ''". */
skillsnice_usage(); skillsnice_usage();
snprintf(path, 32, "/dev/%s", argptr); snprintf(path, 32, "/dev/%s", optarg);
if (stat(path, &sbuf) >= 0 if (stat(path, &sbuf) >= 0
&& S_ISCHR(sbuf.st_mode)) { && S_ISCHR(sbuf.st_mode)) {
num_found++; num_found++;
ENLIST(tty, sbuf.st_rdev); ENLIST(tty, sbuf.st_rdev);
if (!NEXTARG) if (!NEXTARG)
break; break;
} else if (!(argptr[1])) { } else if (!(optarg[1])) {
/* if only 1 character */ /* if only 1 character */
switch (*argptr) { switch (*optarg) {
default: default:
if (stat(argptr, &sbuf) < 0) if (stat(optarg, &sbuf) < 0)
/* the shell eats '?' */ /* the shell eats '?' */
break; break;
case '-': case '-':
@ -611,10 +588,9 @@ static void skillsnice_parse(int argc,
} }
} }
} }
if (force) break;
continue;
case 'u': case 'u':
if (argc) { {
struct passwd *passwd_data; struct passwd *passwd_data;
passwd_data = getpwnam(argptr); passwd_data = getpwnam(argptr);
if (passwd_data) { if (passwd_data) {
@ -624,68 +600,52 @@ static void skillsnice_parse(int argc,
break; 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; break;
} case 'v':
} run_time->verbose = 1;
if (force)
continue;
if (num_found)
/* could still be an option */
continue;
case 'c':
if (argc) {
num_found++;
ENLIST(cmd, argptr);
if (!NEXTARG)
break; break;
case 'w':
run_time->warnings = 1;
break;
case 'h':
skillsnice_usage();
case 'V':
display_kill_version();
exit(EXIT_SUCCESS);
default:
skillsnice_usage();
} }
} /* END OF SWITCH */
} /* END OF WHILE */ argc -= optind;
argv += optind;
for (i = 0; i < argc; i++) {
ENLIST(pid, strtol_or_err(argv[0],
_("failed to parse argument")));
pid_count++;
argv++;
}
/* No more arguments to process. Must sanity check. */ /* No more arguments to process. Must sanity check. */
if (!tty_count && !uid_count && !cmd_count && !pid_count) { if (!tty_count && !uid_count && !cmd_count && !pid_count)
fprintf(stderr, _("ERROR: no process selection criteria.\n")); errx(EXIT_FAILURE, _("no process selection criteria"));
skillsnice_usage(); if ((run_time->fast | run_time->interactive | run_time->
} verbose | run_time->warnings | run_time->noaction) & ~1)
if ((run_time->fast | run_time->interactive | run_time->verbose | run_time->warnings | run_time->noaction) & ~1) { errx(EXIT_FAILURE, _("general flags may not be repeated"));
fprintf(stderr, if (run_time->interactive
_("ERROR: general flags may not be repeated.\n")); && (run_time->verbose | run_time->fast | run_time->noaction))
skillsnice_usage(); errx(EXIT_FAILURE, _("-i makes no sense with -v, -f, and -n"));
} if (run_time->verbose && (run_time->interactive | run_time->fast))
if (run_time->interactive && (run_time->verbose | run_time->fast | run_time->noaction)) { errx(EXIT_FAILURE, _("-v makes no sense with -i and -f"));
fprintf(stderr,
_("ERROR: -i makes no sense with -v, -f, and -n.\n"));
skillsnice_usage();
}
if (run_time->verbose && (run_time->interactive | run_time->fast)) {
fprintf(stderr,
_("ERROR: -v makes no sense with -i and -f.\n"));
skillsnice_usage();
}
/* OK, set up defaults */
if (prino == NO_PRI_VAL)
prino = DEFAULT_NICE;
if (signo < 0)
signo = SIGTERM;
if (run_time->noaction) { if (run_time->noaction) {
program = PROG_SKILL; program = PROG_SKILL;
/* harmless */ /* harmless */
signo = 0; sig_or_pri = 0;
} }
if (program == PROG_SKILL) if (program == PROG_SNICE)
sig_or_pri = signo;
else
sig_or_pri = prino; sig_or_pri = prino;
else if (sig_or_pri < 0)
sig_or_pri = SIGTERM;
} }
/* main body */ /* main body */