diff --git a/pgrep.1 b/pgrep.1 index 6948b323..bc0c9720 100644 --- a/pgrep.1 +++ b/pgrep.1 @@ -81,6 +81,11 @@ List the process name as well as the process ID. .RB ( pgrep only.) .TP +\fB\-a\fR, \fB\-\-list\-full\fR +List the full command line as well as the process ID. +.RB ( pgrep +only.) +.TP \fB\-n\fR, \fB\-\-newest\fR Select only the newest (most recently started) of the matching processes. .TP diff --git a/pgrep.c b/pgrep.c index 84f955f9..37c7d6cc 100644 --- a/pgrep.c +++ b/pgrep.c @@ -41,6 +41,8 @@ #define EXIT_FATAL 3 #define XALLOC_EXIT_CODE EXIT_FATAL +#define CMDSTRSIZE 4096 + #include "c.h" #include "fileutils.h" #include "nls.h" @@ -62,6 +64,7 @@ struct el { static int opt_full = 0; static int opt_long = 0; +static int opt_longlong = 0; static int opt_oldest = 0; static int opt_newest = 0; static int opt_negate = 0; @@ -449,7 +452,9 @@ static struct el * select_procs (int *num) regex_t *preg; pid_t myself = getpid(); struct el *list = NULL; - char cmd[4096]; + char cmdline[CMDSTRSIZE]; + char cmdsearch[CMDSTRSIZE]; + char cmdoutput[CMDSTRSIZE]; ptp = do_openproc(); preg = do_regcomp(); @@ -494,30 +499,38 @@ static struct el * select_procs (int *num) match = match_strlist (tty, opt_term); } } - if (opt_long || (match && opt_pattern)) { - if (opt_full && task.cmdline) { - int i = 0; - int bytes = sizeof (cmd) - 1; + if (task.cmdline && (opt_longlong || opt_full) && match && opt_pattern) { + int i = 0; + int bytes = sizeof (cmdline) - 1; - /* make sure it is always NUL-terminated */ - cmd[bytes] = 0; - /* make room for SPC in loop below */ - --bytes; + /* make sure it is always NUL-terminated */ + cmdline[bytes] = 0; + /* make room for SPC in loop below */ + --bytes; - strncpy (cmd, task.cmdline[i], bytes); - bytes -= strlen (task.cmdline[i++]); - while (task.cmdline[i] && bytes > 0) { - strncat (cmd, " ", bytes); - strncat (cmd, task.cmdline[i], bytes); - bytes -= strlen (task.cmdline[i++]) + 1; - } - } else { - strcpy (cmd, task.cmd); + strncpy (cmdline, task.cmdline[i], bytes); + bytes -= strlen (task.cmdline[i++]); + while (task.cmdline[i] && bytes > 0) { + strncat (cmdline, " ", bytes); + strncat (cmdline, task.cmdline[i], bytes); + bytes -= strlen (task.cmdline[i++]) + 1; } } + if (opt_long || opt_longlong || (match && opt_pattern)) { + if (opt_longlong && task.cmdline) + strncpy (cmdoutput, cmdline, CMDSTRSIZE); + else + strncpy (cmdoutput, task.cmd, CMDSTRSIZE); + } + if (match && opt_pattern) { - if (regexec (preg, cmd, 0, NULL, 0) != 0) + if (opt_full && task.cmdline) + strncpy (cmdsearch, cmdline, CMDSTRSIZE); + else + strncpy (cmdsearch, task.cmd, CMDSTRSIZE); + + if (regexec (preg, cmdsearch, 0, NULL, 0) != 0) match = 0; } @@ -542,9 +555,9 @@ static struct el * select_procs (int *num) size = size * 5 / 4 + 4; list = xrealloc(list, size * sizeof *list); } - if (list && (opt_long || opt_echo)) { + if (list && (opt_long || opt_longlong || opt_echo)) { list[matches].num = task.XXXID; - list[matches++].str = xstrdup (cmd); + list[matches++].str = xstrdup (cmdoutput); } else if (list) { list[matches++].num = task.XXXID; } else { @@ -593,6 +606,7 @@ static void parse_opts (int argc, char **argv) {"count", no_argument, NULL, 'c'}, {"delimeter", required_argument, NULL, 'd'}, {"list-name", no_argument, NULL, 'l'}, + {"list-full", no_argument, NULL, 'a'}, {"full", no_argument, NULL, 'f'}, {"pgroup", required_argument, NULL, 'g'}, {"group", required_argument, NULL, 'G'}, @@ -623,7 +637,7 @@ static void parse_opts (int argc, char **argv) strcat (opts, "e"); } else { /* These options are for pgrep only */ - strcat (opts, "cld:v"); + strcat (opts, "clad:v"); } strcat (opts, "LF:fnoxP:g:s:u:U:G:t:?Vh"); @@ -707,6 +721,9 @@ static void parse_opts (int argc, char **argv) case 'l': /* Solaris: long output format (pgrep only) Should require -f for beyond argv[0] maybe? */ opt_long = 1; break; + case 'a': + opt_longlong = 1; + break; case 'n': /* Solaris: match only the newest */ if (opt_oldest|opt_negate|opt_newest) usage (opt); @@ -814,7 +831,7 @@ int main (int argc, char **argv) if (opt_count) { fprintf(stdout, "%d\n", num); } else { - if (opt_long) + if (opt_long || opt_longlong) output_strlist (procs,num); else output_numlist (procs,num); diff --git a/testsuite/config/unix.exp b/testsuite/config/unix.exp index 9092b9d4..d9100e4e 100644 --- a/testsuite/config/unix.exp +++ b/testsuite/config/unix.exp @@ -111,11 +111,11 @@ proc expect_table_dsc { test match_header match_item } { } proc make_testproc { } { + global testproc_path testproc_comm testproc1_pid testproc2_pid sleep_time + # Time to run the whole job set sleep_time 300 - global testproc_path testproc_comm testproc1_pid testproc2_pid - set testproc_path [ exec mktemp -u ] set sleep_path [ exec which sleep ] exec ln -s $sleep_path $testproc_path diff --git a/testsuite/pgrep.test/pgrep.exp b/testsuite/pgrep.test/pgrep.exp index 0ec52c37..0cb6db78 100644 --- a/testsuite/pgrep.test/pgrep.exp +++ b/testsuite/pgrep.test/pgrep.exp @@ -51,6 +51,10 @@ set test "pgrep with process name" spawn $pgrep -l $testproc_comm expect_pass "$test" "^$testproc1_pid\\s+$testproc_comm\\s+$testproc2_pid\\s+$testproc_comm\\s*$" +set test "pgrep with full command line" +spawn $pgrep -a $testproc_comm +expect_pass "$test" "^$testproc1_pid\\s+$testproc_path\\s+$sleep_time\\s+$testproc2_pid\\s+$testproc_path\\s+$sleep_time\\s*$" + set test "pgrep find newest test pid" spawn $pgrep -n $testproc_comm expect_pass "$test" "^$testproc2_pid\\s*$"