]> granicus.if.org Git - procps-ng/commitdiff
pgrep: Allow older than selection
authorCraig Small <csmall@dropbear.xyz>
Sun, 17 May 2020 13:00:27 +0000 (23:00 +1000)
committerCraig Small <csmall@dropbear.xyz>
Sun, 17 May 2020 13:00:27 +0000 (23:00 +1000)
Re-work merge request !79 of @edneville to permit older than
selection using the new library API.

References:
 procps-ng/procps!79

NEWS
pgrep.1
pgrep.c

diff --git a/NEWS b/NEWS
index fb83a6727518d39d24e418df60819cedb772b233..083391a6f2357f41698defd7701eeed25351f196 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ procps-ng NEXT
   * kill: Pass int to signalled process                    merge #32
   * pgrep: Pass int to signalled process                   merge #32
   * pgrep: Check sanity of SG_ARG_MAX                      issue #152
+  * pgrep: Add older than selection                        merge #79
   * pidof: show worker threads                             Redhat #1803640
   * ps.1: Mention stime alias                              issue #164
   * sysctl: Match systemd directory order
diff --git a/pgrep.1 b/pgrep.1
index f626a6bbce375b82d625eeb7082e2a5a97272ae3..6dc4081d1e6eba1bc0cf49522cdd42210816bdd2 100644 (file)
--- a/pgrep.1
+++ b/pgrep.1
@@ -7,7 +7,7 @@
 .\" the Free Software Foundation; either version 2 of the License, or
 .\" (at your option) any later version.
 .\"
-.TH PGREP "1" "2020-04-24" "procps-ng" "User Commands"
+.TH PGREP "1" "2020-05-17" "procps-ng" "User Commands"
 .SH NAME
 pgrep, pkill \- look up or signal processes based on name and other attributes
 .SH SYNOPSIS
@@ -100,6 +100,9 @@ Select only the newest (most recently started) of the matching processes.
 \fB\-o\fR, \fB\-\-oldest\fR
 Select only the oldest (least recently started) of the matching processes.
 .TP
+\fB\-O\fR, \fB\-\-older\fR \fIsecs\fP
+Select processes older than secs.
+.TP
 \fB\-P\fR, \fB\-\-parent\fR \fIppid\fP,...
 Only match processes whose parent process ID is listed.
 .TP
diff --git a/pgrep.c b/pgrep.c
index 0123e2db1e6a4cb403d0ee6f9a360e66cc8936a7..a55f49f019000b852cd50381438e232653b30072 100644 (file)
--- a/pgrep.c
+++ b/pgrep.c
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <getopt.h>
 #include <stdbool.h>
+#include <time.h>
 
 /* EXIT_SUCCESS is 0 */
 /* EXIT_FAILURE is 1 */
@@ -63,11 +64,12 @@ enum pids_item Items[] = {
     PIDS_TTY_NAME,
     PIDS_CMD,
     PIDS_CMDLINE,
-    PIDS_STATE
+    PIDS_STATE,
+    PIDS_TIME_ELAPSED
 };
 enum rel_items {
     EU_PID, EU_PPID, EU_PGRP, EU_EUID, EU_RUID, EU_RGID, EU_SESSION,
-    EU_TGID, EU_STARTTIME, EU_TTYNAME, EU_CMD, EU_CMDLINE, EU_STA
+    EU_TGID, EU_STARTTIME, EU_TTYNAME, EU_CMD, EU_CMDLINE, EU_STA, EU_ELAPSED
 };
 #define grow_size(x) do { \
        if ((x) < 0 || (size_t)(x) >= INT_MAX / 5 / sizeof(struct el)) \
@@ -88,6 +90,7 @@ static int opt_full = 0;
 static int opt_long = 0;
 static int opt_longlong = 0;
 static int opt_oldest = 0;
+static int opt_older = 0;
 static int opt_newest = 0;
 static int opt_negate = 0;
 static int opt_exact = 0;
@@ -145,6 +148,7 @@ static int __attribute__ ((__noreturn__)) usage(int opt)
     fputs(_(" -i, --ignore-case         match case insensitively\n"), fp);
     fputs(_(" -n, --newest              select most recently started\n"), fp);
     fputs(_(" -o, --oldest              select least recently started\n"), fp);
+    fputs(_(" -O, --older <seconds>     select where older than seconds\n"), fp);
     fputs(_(" -P, --parent <PPID,...>   match only child processes of the given parent\n"), fp);
     fputs(_(" -s, --session <SID,...>   match session IDs\n"), fp);
     fputs(_(" -t, --terminal <tty,...>  match by controlling terminal\n"), fp);
@@ -525,9 +529,15 @@ static struct el * select_procs (int *num)
     char *cmdoutput = xmalloc(cmdlen);
     char *task_cmdline;
     enum pids_fetch_type which;
+    time_t now;
+    double uptime_secs;
 
     preg = do_regcomp();
 
+    now = time(NULL);
+    if (procps_uptime(&uptime_secs, NULL) < 0)
+        xerrx(EXIT_FAILURE, "uptime");
+
     if (opt_newest) saved_start_time =  0ULL;
     else saved_start_time = ~0ULL;
 
@@ -538,7 +548,7 @@ static struct el * select_procs (int *num)
               _("Error reading reference namespace information\n"));
     }
 
-    if (procps_pids_new(&info, Items, 13) < 0)
+    if (procps_pids_new(&info, Items, 14) < 0)
         xerrx(EXIT_FATAL,
               _("Unable to create pid info structure"));
     which = PIDS_FETCH_TASKS_ONLY;
@@ -570,9 +580,11 @@ static struct el * select_procs (int *num)
             match = 0;
         else if (opt_ns_pid && ! match_ns (PIDS_GETINT(PID), &nsp))
             match = 0;
+       else if (opt_older && PIDS_GETULL(ELAPSED) < opt_older)
+           match = 0;
         else if (opt_term)
             match = match_strlist(PIDS_GETSTR(TTYNAME), opt_term);
-               else if (opt_runstates && ! strchr(opt_runstates, PIDS_GETSCH(STA)))
+        else if (opt_runstates && ! strchr(opt_runstates, PIDS_GETSCH(STA)))
             match = 0;
 
         task_cmdline = PIDS_GETSTR(CMDLINE);
@@ -686,6 +698,7 @@ static void parse_opts (int argc, char **argv)
         {"ignore-case", no_argument, NULL, 'i'},
         {"newest", no_argument, NULL, 'n'},
         {"oldest", no_argument, NULL, 'o'},
+        {"older", required_argument, NULL, 'O'},
         {"parent", required_argument, NULL, 'P'},
         {"session", required_argument, NULL, 's'},
         {"terminal", required_argument, NULL, 't'},
@@ -719,7 +732,7 @@ static void parse_opts (int argc, char **argv)
         strcat (opts, "lad:vw");
     }
 
-    strcat (opts, "LF:cfinoxP:g:s:u:U:G:t:r:?Vh");
+    strcat (opts, "LF:cfinoxP:O:g:s:u:U:G:t:r:?Vh");
 
     while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) {
         switch (opt) {
@@ -815,6 +828,10 @@ static void parse_opts (int argc, char **argv)
             opt_oldest = 1;
             ++criteria_count;
             break;
+        case 'O':
+            opt_older = atoi (optarg);
+           ++criteria_count;
+           break;
         case 's':   /* Solaris: match by session ID -- zero means self */
             opt_sid = split_list (optarg, conv_sid);
             if (opt_sid == NULL)