Skip to content

Commit

Permalink
libpcp, pcp-xsos: finer grained string output control in pmPrintValue
Browse files Browse the repository at this point in the history
Implement a mechanism in pmPrintValue for producing single-line value
output, giving shell scripts a chance to operate sensibly with whacky
command lines.

Resolves Red Hat bugs RHEL-67164 and RHEL-67148.
  • Loading branch information
natoscott committed Nov 13, 2024
1 parent a55c5de commit d2852e1
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 2 deletions.
9 changes: 9 additions & 0 deletions man/man3/pmprintvalue.3
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ and
pairs for each requested metric), based upon the
metrics type as returned from
.BR pmLookupDesc (3).
.SH ENVIRONMENT
Output of string metric values can be further controlled using
.BR PCP_SQUASH_NEWLINES .
When set in the environment of the calling process, and the
.I type
is set to PM_TYPE_STRING or PM_TYPE_AGGREGATE, then the output
value is guaranteed to be free of embedded newline characters.
If the given value contained such characters, they will have been
replaced by a space before being printed.
.SH SEE ALSO
.BR PMAPI (3),
.BR pmAtomStr (3),
Expand Down
28 changes: 28 additions & 0 deletions qa/1564
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,33 @@ pcp -a $archive xsos -x -n | _filter_net
echo === Archive pcp xsos -N
pcp -a $archive xsos -x -N | _filter_netstat

echo === Special case: eval command issues | tee -a $seq.full
test -f /eperm && $sudo rm -f /eperm
(./src/args \$\(touch /eperm\) )&
argspid=$!
$PCP_BINADM_DIR/pmsleep 0.25 # start args
$sudo pcp xsos -x --ps >> $seq.full
echo $? exit status
test -f /eperm && echo file exists && $sudo rm -f /eperm
$PCP_BINADM_DIR/pmsignal $argspid
wait $argspid

echo === Special case: multiline ps issues | tee -a $seq.full
(./src/args '
multi
line
args
')&
argspid=$!
$PCP_BINADM_DIR/pmsleep 0.25 # start args
pcp xsos -x --ps >> $seq.full
echo $? exit status
$PCP_BINADM_DIR/pmsignal $argspid
wait $argspid

echo === Special case: command line errors | tee -a $seq.full
pcp xsos unknown_arg >> $seq.full 2>&1
echo $? exit status

# success, all done
exit
6 changes: 6 additions & 0 deletions qa/1564.out
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,9 @@ NET STATS
Ip.InAddrErrors: XXX
Ip6.InAddrErrors: XXX

=== Special case: eval command issues
0 exit status
=== Special case: multiline ps issues
0 exit status
=== Special case: command line errors
1 exit status
1 change: 1 addition & 0 deletions qa/src/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ archend
archfetch
archinst
arch_maxfd
args
atomstr
badUnitsStr_r
badloglabel
Expand Down
2 changes: 1 addition & 1 deletion qa/src/GNUlocaldefs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ CFILES = disk_test.c exercise.c context_test.c chkoptfetch.c \
archctl_segfault.c debug.c int2pmid.c int2indom.c exectest.c \
unpickargs.c hanoi.c progname.c countmark.c check_attribute.c \
indom2int.c pmid2int.c scanmeta.c traverse_return_codes.c \
timeshift.c checkstructs.c bcc_profile.c sha1int2ext.c \
timeshift.c checkstructs.c bcc_profile.c args.c sha1int2ext.c \
getdomainname.c profilecrash.c store_and_fetch.c test_service_notify.c \
ctx_derive.c pmstrn.c pmfstring.c pmfg-derived.c mmv_help.c sizeof.c \
stampconv.c time_stamp.c archend.c scandata.c wait_for_values.c \
Expand Down
18 changes: 18 additions & 0 deletions qa/src/args.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright (c) 2024 Red Hat.
*
* QA helper that waits for stdin input then exits, useful for
* shell escape testing as it allows arbitrary args (ignored).
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
while (1)
sleep(1);
exit(EXIT_SUCCESS);
}
2 changes: 2 additions & 0 deletions src/libpcp/src/check-statics
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ util.o
msgbuf # guarded by util_lock mutex
msgbuflen # guarded by util_lock mutex
msgsize # guarded by util_lock mutex
squashed # guarded by __pmLock_extcall mutex when set
# in a one-trip initialization
filename # guarded by __pmLock_extcall mutex when set
# in a one-trip initialization
?base # no unsafe side-effects, see notes in util.c
Expand Down
29 changes: 28 additions & 1 deletion src/libpcp/src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,18 @@ print_event_summary(FILE *f, const pmValue *val, int highres)
fputc(']', f);
}

static void
squash_string(char *s, unsigned int len)
{
unsigned int i;

/* replace end-of-line characters */
for (i = 0; i < len; i++) {
if (isspace(s[i]))
s[i] = ' ';
}
}

/* Print single pmValue. */
void
pmPrintValue(FILE *f, /* output stream */
Expand All @@ -997,6 +1009,16 @@ pmPrintValue(FILE *f, /* output stream */
int n;
char *p;
int sts;
static int squashed = -1;

if (squashed == -1) {
/* one-trip initialization */
PM_LOCK(__pmLock_extcall);
squashed = 0;
if (getenv("PCP_SQUASH_NEWLINES") != NULL) /* THREADSAFE */
squashed = 1;
PM_UNLOCK(__pmLock_extcall);
}

if (type != PM_TYPE_UNKNOWN &&
type != PM_TYPE_EVENT &&
Expand Down Expand Up @@ -1032,7 +1054,10 @@ pmPrintValue(FILE *f, /* output stream */
break;

case PM_TYPE_STRING:
n = (int)strlen(a.cp) + 2;
n = (int)strlen(a.cp);
if (squashed)
squash_string(a.cp, n);
n += 2;
while (n < minwidth) {
fputc(' ', f);
n++;
Expand Down Expand Up @@ -1123,6 +1148,8 @@ pmPrintValue(FILE *f, /* output stream */
n++;
}
n = (int)val->value.pval->vlen - PM_VAL_HDR_SIZE;
if (squashed)
squash_string(val->value.pval->vbuf, n);
fprintf(f, "\"%*.*s\"", n, n, val->value.pval->vbuf);
done = 1;
}
Expand Down

0 comments on commit d2852e1

Please sign in to comment.