From 60ea57b6efcb3028474baf572f59e006964a0756 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Wed, 16 Dec 2009 06:55:44 +0000 Subject: [PATCH] minor prtstat changes and killall ages --- src/killall.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++--- src/prtstat.c | 3 - src/prtstat.h | 15 ----- src/pstree.c | 19 +++--- 4 files changed, 175 insertions(+), 33 deletions(-) diff --git a/src/killall.c b/src/killall.c index bc4cf15..c89de73 100644 --- a/src/killall.c +++ b/src/killall.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #ifdef WITH_SELINUX #include @@ -50,13 +52,33 @@ #include "comm.h" #include "signals.h" - #define PROC_BASE "/proc" #define MAX_NAMES (int)(sizeof(unsigned long)*8) +#define TSECOND "sec" +#define TMINUTE "min" +#define THOUR "hour" +#define TDAY "day" +#define TWEEK "WEEK" +#define TMONTH "MON" +#define TYEAR "YEAR" + +#define TMAX_SECOND 31536000 +#define TMAX_MINUTE 525600 +#define TMAX_HOUR 8760 +#define TMAX_DAY 365 +#define TMAX_WEEK 48 +#define TMAX_MONTH 12 +#define TMAX_YEAR 1 + +#define ER_REGFAIL -1 +#define ER_NOMEM -2 +#define ER_UNKWN -3 +#define ER_OOFRA -4 static int verbose = 0, exact = 0, interactive = 0, reg = 0, quiet = 0, wait_until_dead = 0, process_group = 0, + younger_than = 0, older_than = 0, ignore_case = 0, pidof; static int @@ -95,6 +117,101 @@ ask (char *name, pid_t pid, const int signal) /* Never should get here */ } +static double +uptime() +{ + char * savelocale; + char buf[2048]; + FILE* file; + if (!(file=fopen( PROC_BASE "/uptime", "r"))) { + fprintf(stderr, "error opening uptime file\n"); + exit(1); + } + savelocale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC,"C"); + fscanf(file, "%s", buf); + fclose(file); + setlocale(LC_NUMERIC,savelocale); + return atof(buf); +} + +/* process age from jiffies to seconds via uptime */ +static double process_age(const unsigned jf) +{ + double sc_clk_tck = sysconf(_SC_CLK_TCK); + assert(sc_clk_tck > 0); + return uptime() - jf / sc_clk_tck; +} + +/* returns requested time interval in seconds, + negative indicates error has occured + */ +static time_t +parse_time_units(const char* age) +{ + regex_t preg; + if ( 0 == regcomp(&preg, "^[0-9]{1,8}[a-zA-Z]{1,8}$", REG_NOSUB | REG_EXTENDED)) { + int ret = regexec(&preg, age, (size_t)0, NULL, 0); + regfree(&preg); + if ( 0 != ret ) + return ER_REGFAIL; + } + + time_t res; + char * savelocale; + savelocale = setlocale(LC_ALL, NULL); + setlocale(LC_NUMERIC,"C"); + + unsigned int i; + for (i=0; ipw_uid)==0) continue; @@ -281,9 +398,24 @@ kill_all (int signal, int names, char **namelist, struct passwd *pwent) } free (path); okay = fscanf (file, "%*d (%15[^)]", comm) == 1; - (void) fclose (file); - if (!okay) + if (!okay) { + fclose(file); continue; + } + if ( younger_than || older_than ) { + rewind(file); + unsigned int proc_stt_jf = 0; + okay = fscanf(file, "%*d %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %ull", + &proc_stt_jf) == 1; + if (!okay) { + fclose(file); + continue; + } + process_age_sec = process_age(proc_stt_jf); + assert(process_age_sec > 0); + } + (void) fclose (file); + got_long = 0; command = NULL; /* make gcc happy */ length = strlen (comm); @@ -356,6 +488,11 @@ kill_all (int signal, int names, char **namelist, struct passwd *pwent) } else /* non-regex */ { + if ( younger_than && process_age_sec && (process_age_sec > younger_than ) ) + continue; + if ( older_than && process_age_sec && (process_age_sec < older_than ) ) + continue; + if (!sts[j].st_dev) { if (length != COMM_LEN - 1 || name_len[j] < COMM_LEN - 1) @@ -531,6 +668,8 @@ usage_killall (void) " -e,--exact require exact match for very long names\n" " -I,--ignore-case case insensitive process name match\n" " -g,--process-group kill process group instead of process\n" + " -y,--younger-than kill processes younger than Nsec,min,hour,day,WEEK,MON,YEAR\n" + " -o,--older-than kill processes older than Nsec,min,hour,day,WEEK,MON,YEAR\n" " -i,--interactive ask for confirmation before killing\n" " -l,--list list all known signal names\n" " -q,--quiet don't print complaints\n" @@ -580,13 +719,17 @@ main (int argc, char **argv) int myoptind; struct passwd *pwent = NULL; struct stat isproc; - + char yt[16]; + char ot[16]; + //int optsig = 0; struct option options[] = { {"exact", 0, NULL, 'e'}, {"ignore-case", 0, NULL, 'I'}, {"process-group", 0, NULL, 'g'}, + {"younger-than", 1, NULL, 'y'}, + {"older-than", 1, NULL, 'o'}, {"interactive", 0, NULL, 'i'}, {"list-signals", 0, NULL, 'l'}, {"quiet", 0, NULL, 'q'}, @@ -625,9 +768,9 @@ main (int argc, char **argv) opterr = 0; #ifdef WITH_SELINUX - while ( (optc = getopt_long_only(argc,argv,"egilqrs:u:vwZ:VI",options,NULL)) != -1) { + while ( (optc = getopt_long_only(argc,argv,"egy:o:ilqrs:u:vwZ:VI",options,NULL)) != -1) { #else - while ( (optc = getopt_long_only(argc,argv,"egilqrs:u:vwVI",options,NULL)) != -1) { + while ( (optc = getopt_long_only(argc,argv,"egy:o:ilqrs:u:vwVI",options,NULL)) != -1) { #endif switch (optc) { case 'e': @@ -636,6 +779,20 @@ main (int argc, char **argv) case 'g': process_group = 1; break; + case 'y': + if (pidof) + usage(); + strncpy(yt, optarg, 16); + if ( 0 >= (younger_than = parse_time_units(yt) ) ) + usage(); + break; + case 'o': + if (pidof) + usage(); + strncpy(ot, optarg, 16); + if ( 0 >= (older_than = parse_time_units(ot) ) ) + usage(); + break; case 'i': if (pidof) usage(); diff --git a/src/prtstat.c b/src/prtstat.c index 92a1fb3..cb2000e 100644 --- a/src/prtstat.c +++ b/src/prtstat.c @@ -214,9 +214,6 @@ static void print_stat(const int pid, const opt_type options) char *bptr; FILE *fp; - struct proc_statnames psn[] = { - {"d", "blah", (union proc_values)3} - }; struct proc_info *pr; pr = malloc(sizeof(struct proc_info)); diff --git a/src/prtstat.h b/src/prtstat.h index f3f93e1..64c724f 100644 --- a/src/prtstat.h +++ b/src/prtstat.h @@ -19,18 +19,3 @@ struct proc_info unsigned long long starttime, blkio; }; -union proc_values { - int d; - char c; - long x; - unsigned long lu; - long ld; - unsigned long long lX; -}; - - -struct proc_statnames { - char fmt[3]; - char *name; - union proc_values value; -}; diff --git a/src/pstree.c b/src/pstree.c index 4ec5c44..478563d 100644 --- a/src/pstree.c +++ b/src/pstree.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -416,6 +417,7 @@ dump_tree(PROC * current, int level, int rep, int leaf, int last, int lvl, i, add, offset, len, swapped, info, count, comm_len, first; const char *tmp, *here; + assert(closing >= 0); if (!current) return; if (!leaf) @@ -484,7 +486,7 @@ dump_tree(PROC * current, int level, int rep, int leaf, int last, if (print_args || !current->children) #endif /*WITH_SELINUX */ { - while (closing-- > 0) + while (closing--) out_char(']'); out_newline(); } @@ -499,25 +501,26 @@ dump_tree(PROC * current, int level, int rep, int leaf, int last, { width[level] = swapped + (comm_len > 1 ? 0 : -1); count=0; + first=1; for (walk = current->children; walk; walk = next) { next = walk->next; count=0; if (compact && (walk->child->flags & PFLAG_THREAD)) { scan = &walk->next; while (*scan) { - if (tree_equal(walk->child, (*scan)->child)) { - count++; + if (!tree_equal(walk->child, (*scan)->child)) { scan = &(*scan)->next; } else { - next = (*scan)->next; - scan = NULL; + if (next == *scan) + next = (*scan)->next; + count++; + *scan = (*scan)->next; } } dump_tree(walk->child, level + 1, count + 1, - walk == current->children, !next, current->uid, - closing + (count ? 1 : 0)); + 0, !next, current->uid, closing+ (count ? 2 : 1)); + //closing + (count ? 1 : 0)); } else { - count = 0; dump_tree(walk->child, level + 1, 1, 0, !walk->next, current->uid, 0); } -- 2.40.0