|
| 1 | +commit d2852e19e77e25d628399d51fcf199233547f8c4 |
| 2 | +Author: Nathan Scott < [email protected]> |
| 3 | +Date: Wed Nov 13 17:17:28 2024 +1100 |
| 4 | + |
| 5 | + libpcp, pcp-xsos: finer grained string output control in pmPrintValue |
| 6 | + |
| 7 | + Implement a mechanism in pmPrintValue for producing single-line value |
| 8 | + output, giving shell scripts a chance to operate sensibly with whacky |
| 9 | + command lines. |
| 10 | + |
| 11 | + Resolves Red Hat bugs RHEL-67164 and RHEL-67148. |
| 12 | + |
| 13 | +diff --git a/man/man3/pmprintvalue.3 b/man/man3/pmprintvalue.3 |
| 14 | +index 067b2aee2b..656c05849d 100644 |
| 15 | +--- a/man/man3/pmprintvalue.3 |
| 16 | ++++ b/man/man3/pmprintvalue.3 |
| 17 | +@@ -80,6 +80,15 @@ and |
| 18 | + pairs for each requested metric), based upon the |
| 19 | + metrics type as returned from |
| 20 | + .BR pmLookupDesc (3). |
| 21 | ++.SH ENVIRONMENT |
| 22 | ++Output of string metric values can be further controlled using |
| 23 | ++.BR PCP_SQUASH_NEWLINES . |
| 24 | ++When set in the environment of the calling process, and the |
| 25 | ++.I type |
| 26 | ++is set to PM_TYPE_STRING or PM_TYPE_AGGREGATE, then the output |
| 27 | ++value is guaranteed to be free of embedded newline characters. |
| 28 | ++If the given value contained such characters, they will have been |
| 29 | ++replaced by a space before being printed. |
| 30 | + .SH SEE ALSO |
| 31 | + .BR PMAPI (3), |
| 32 | + .BR pmAtomStr (3), |
| 33 | +diff --git a/qa/1564 b/qa/1564 |
| 34 | +index cbb976cfe4..714955223e 100755 |
| 35 | +--- a/qa/1564 |
| 36 | ++++ b/qa/1564 |
| 37 | +@@ -117,5 +117,33 @@ pcp -a $archive xsos -x -n | _filter_net |
| 38 | + echo === Archive pcp xsos -N |
| 39 | + pcp -a $archive xsos -x -N | _filter_netstat |
| 40 | + |
| 41 | ++echo === Special case: eval command issues | tee -a $seq.full |
| 42 | ++test -f /eperm && $sudo rm -f /eperm |
| 43 | ++(./src/args \$\(touch /eperm\) )& |
| 44 | ++argspid=$! |
| 45 | ++$PCP_BINADM_DIR/pmsleep 0.25 # start args |
| 46 | ++$sudo pcp xsos -x --ps >> $seq.full |
| 47 | ++echo $? exit status |
| 48 | ++test -f /eperm && echo file exists && $sudo rm -f /eperm |
| 49 | ++$PCP_BINADM_DIR/pmsignal $argspid |
| 50 | ++wait $argspid |
| 51 | ++ |
| 52 | ++echo === Special case: multiline ps issues | tee -a $seq.full |
| 53 | ++(./src/args ' |
| 54 | ++multi |
| 55 | ++line |
| 56 | ++args |
| 57 | ++')& |
| 58 | ++argspid=$! |
| 59 | ++$PCP_BINADM_DIR/pmsleep 0.25 # start args |
| 60 | ++pcp xsos -x --ps >> $seq.full |
| 61 | ++echo $? exit status |
| 62 | ++$PCP_BINADM_DIR/pmsignal $argspid |
| 63 | ++wait $argspid |
| 64 | ++ |
| 65 | ++echo === Special case: command line errors | tee -a $seq.full |
| 66 | ++pcp xsos unknown_arg >> $seq.full 2>&1 |
| 67 | ++echo $? exit status |
| 68 | ++ |
| 69 | + # success, all done |
| 70 | + exit |
| 71 | +diff --git a/qa/1564.out b/qa/1564.out |
| 72 | +index 57de00c30a..11321e342a 100644 |
| 73 | +--- a/qa/1564.out |
| 74 | ++++ b/qa/1564.out |
| 75 | +@@ -111,3 +111,9 @@ NET STATS |
| 76 | + Ip.InAddrErrors: XXX |
| 77 | + Ip6.InAddrErrors: XXX |
| 78 | + |
| 79 | ++=== Special case: eval command issues |
| 80 | ++0 exit status |
| 81 | ++=== Special case: multiline ps issues |
| 82 | ++0 exit status |
| 83 | ++=== Special case: command line errors |
| 84 | ++1 exit status |
| 85 | +diff --git a/qa/src/.gitignore b/qa/src/.gitignore |
| 86 | +index 7e9b0fe08a..3399d24a4e 100644 |
| 87 | +--- a/qa/src/.gitignore |
| 88 | ++++ b/qa/src/.gitignore |
| 89 | +@@ -13,6 +13,7 @@ archend |
| 90 | + archfetch |
| 91 | + archinst |
| 92 | + arch_maxfd |
| 93 | ++args |
| 94 | + atomstr |
| 95 | + badUnitsStr_r |
| 96 | + badloglabel |
| 97 | +diff --git a/qa/src/GNUlocaldefs b/qa/src/GNUlocaldefs |
| 98 | +index ae647278f2..ac0920d136 100644 |
| 99 | +--- a/qa/src/GNUlocaldefs |
| 100 | ++++ b/qa/src/GNUlocaldefs |
| 101 | +@@ -48,7 +48,7 @@ CFILES = disk_test.c exercise.c context_test.c chkoptfetch.c \ |
| 102 | + archctl_segfault.c debug.c int2pmid.c int2indom.c exectest.c \ |
| 103 | + unpickargs.c hanoi.c progname.c countmark.c check_attribute.c \ |
| 104 | + indom2int.c pmid2int.c scanmeta.c traverse_return_codes.c \ |
| 105 | +- timeshift.c checkstructs.c bcc_profile.c sha1int2ext.c \ |
| 106 | ++ timeshift.c checkstructs.c bcc_profile.c args.c sha1int2ext.c \ |
| 107 | + getdomainname.c profilecrash.c store_and_fetch.c test_service_notify.c \ |
| 108 | + ctx_derive.c pmstrn.c pmfstring.c pmfg-derived.c mmv_help.c sizeof.c \ |
| 109 | + stampconv.c time_stamp.c archend.c scandata.c wait_for_values.c \ |
| 110 | +diff --git a/qa/src/args.c b/qa/src/args.c |
| 111 | +new file mode 100644 |
| 112 | +index 0000000000..06d9b9b6cc |
| 113 | +--- /dev/null |
| 114 | ++++ b/qa/src/args.c |
| 115 | +@@ -0,0 +1,18 @@ |
| 116 | ++/* |
| 117 | ++ * Copyright (c) 2024 Red Hat. |
| 118 | ++ * |
| 119 | ++ * QA helper that waits for stdin input then exits, useful for |
| 120 | ++ * shell escape testing as it allows arbitrary args (ignored). |
| 121 | ++ */ |
| 122 | ++ |
| 123 | ++#include <stdio.h> |
| 124 | ++#include <stdlib.h> |
| 125 | ++#include <unistd.h> |
| 126 | ++ |
| 127 | ++int |
| 128 | ++main(int argc, char **argv) |
| 129 | ++{ |
| 130 | ++ while (1) |
| 131 | ++ sleep(1); |
| 132 | ++ exit(EXIT_SUCCESS); |
| 133 | ++} |
| 134 | +diff --git a/src/libpcp/src/check-statics b/src/libpcp/src/check-statics |
| 135 | +index 29dcb868ad..b9f21edc32 100755 |
| 136 | +--- a/src/libpcp/src/check-statics |
| 137 | ++++ b/src/libpcp/src/check-statics |
| 138 | +@@ -581,6 +581,8 @@ util.o |
| 139 | + msgbuf # guarded by util_lock mutex |
| 140 | + msgbuflen # guarded by util_lock mutex |
| 141 | + msgsize # guarded by util_lock mutex |
| 142 | ++ squashed # guarded by __pmLock_extcall mutex when set |
| 143 | ++ # in a one-trip initialization |
| 144 | + filename # guarded by __pmLock_extcall mutex when set |
| 145 | + # in a one-trip initialization |
| 146 | + ?base # no unsafe side-effects, see notes in util.c |
| 147 | +diff --git a/src/libpcp/src/util.c b/src/libpcp/src/util.c |
| 148 | +index d4f79ca40d..84a7df6329 100644 |
| 149 | +--- a/src/libpcp/src/util.c |
| 150 | ++++ b/src/libpcp/src/util.c |
| 151 | +@@ -984,6 +984,18 @@ print_event_summary(FILE *f, const pmValue *val, int highres) |
| 152 | + fputc(']', f); |
| 153 | + } |
| 154 | + |
| 155 | ++static void |
| 156 | ++squash_string(char *s, unsigned int len) |
| 157 | ++{ |
| 158 | ++ unsigned int i; |
| 159 | ++ |
| 160 | ++ /* replace end-of-line characters */ |
| 161 | ++ for (i = 0; i < len; i++) { |
| 162 | ++ if (isspace(s[i])) |
| 163 | ++ s[i] = ' '; |
| 164 | ++ } |
| 165 | ++} |
| 166 | ++ |
| 167 | + /* Print single pmValue. */ |
| 168 | + void |
| 169 | + pmPrintValue(FILE *f, /* output stream */ |
| 170 | +@@ -997,6 +1009,16 @@ pmPrintValue(FILE *f, /* output stream */ |
| 171 | + int n; |
| 172 | + char *p; |
| 173 | + int sts; |
| 174 | ++ static int squashed = -1; |
| 175 | ++ |
| 176 | ++ if (squashed == -1) { |
| 177 | ++ /* one-trip initialization */ |
| 178 | ++ PM_LOCK(__pmLock_extcall); |
| 179 | ++ squashed = 0; |
| 180 | ++ if (getenv("PCP_SQUASH_NEWLINES") != NULL) /* THREADSAFE */ |
| 181 | ++ squashed = 1; |
| 182 | ++ PM_UNLOCK(__pmLock_extcall); |
| 183 | ++ } |
| 184 | + |
| 185 | + if (type != PM_TYPE_UNKNOWN && |
| 186 | + type != PM_TYPE_EVENT && |
| 187 | +@@ -1032,7 +1054,10 @@ pmPrintValue(FILE *f, /* output stream */ |
| 188 | + break; |
| 189 | + |
| 190 | + case PM_TYPE_STRING: |
| 191 | +- n = (int)strlen(a.cp) + 2; |
| 192 | ++ n = (int)strlen(a.cp); |
| 193 | ++ if (squashed) |
| 194 | ++ squash_string(a.cp, n); |
| 195 | ++ n += 2; |
| 196 | + while (n < minwidth) { |
| 197 | + fputc(' ', f); |
| 198 | + n++; |
| 199 | +@@ -1123,6 +1148,8 @@ pmPrintValue(FILE *f, /* output stream */ |
| 200 | + n++; |
| 201 | + } |
| 202 | + n = (int)val->value.pval->vlen - PM_VAL_HDR_SIZE; |
| 203 | ++ if (squashed) |
| 204 | ++ squash_string(val->value.pval->vbuf, n); |
| 205 | + fprintf(f, "\"%*.*s\"", n, n, val->value.pval->vbuf); |
| 206 | + done = 1; |
| 207 | + } |
| 208 | + |
| 209 | +commit a55c5de05836ca0e71b052a4579b34f8e6577c23 |
| 210 | +Merge: 3bcaee943a b147af9c8e |
| 211 | +Author: Nathan Scott < [email protected]> |
| 212 | +Date: Wed Nov 13 16:49:57 2024 +1100 |
| 213 | + |
| 214 | + Merge commit 'b147af9c8e71423be9bb62699534d3fea4d86b8a' into xsos |
| 215 | + |
| 216 | + |
| 217 | +commit b147af9c8e71423be9bb62699534d3fea4d86b8a |
| 218 | +Author: Nathan Scott < [email protected]> |
| 219 | +Date: Wed Nov 13 16:49:57 2024 +1100 |
| 220 | + |
| 221 | + Squashed 'vendor/github.com/performancecopilot/xsos-pcp/' changes from deb8740f2f..de2b314859 |
| 222 | + |
| 223 | + de2b314859 pcp-xsos: fine-tune error handling on bad command line options |
| 224 | + 35f2cefa3a pcp-xsos: single-line pmPrintValue/pminfo values, escape shell chars |
| 225 | + |
| 226 | + git-subtree-dir: vendor/github.com/performancecopilot/xsos-pcp |
| 227 | + git-subtree-split: de2b314859d01dec9387e06da39af6920018d219 |
| 228 | + |
| 229 | +diff --git a/pcp-xsos b/pcp-xsos |
| 230 | +index e8c60f1e0c..388712752d 100755 |
| 231 | +--- a/vendor/github.com/performancecopilot/xsos-pcp/pcp-xsos |
| 232 | ++++ b/vendor/github.com/performancecopilot/xsos-pcp/pcp-xsos |
| 233 | +@@ -112,7 +112,6 @@ _usage() |
| 234 | + { |
| 235 | + [ ! -z "$@" ] && echo $@ 1>&2 |
| 236 | + pmgetopt --progname=$progname --usage --config=$tmp/usage |
| 237 | +- sts=0 |
| 238 | + exit |
| 239 | + } |
| 240 | + |
| 241 | +@@ -206,9 +205,11 @@ do |
| 242 | + color=false |
| 243 | + ;; |
| 244 | + -\?) |
| 245 | ++ sts=0 |
| 246 | + _usage "" |
| 247 | + ;; |
| 248 | + --) # end of options, start of arguments |
| 249 | ++ sts=1 |
| 250 | + _usage "Unknown argument: $2" |
| 251 | + ;; |
| 252 | + esac |
| 253 | +@@ -304,6 +305,7 @@ fi |
| 254 | + # kernel_all_load_value[15]=0.06 |
| 255 | + # kernel_cpu_util_user_error="No value(s) available!" |
| 256 | + |
| 257 | ++export PCP_SQUASH_NEWLINES=1 |
| 258 | + if ! pminfo $batch --fetch ${metrics[*]} > $tmp/metrics 2>$tmp/error |
| 259 | + then |
| 260 | + if grep "^pminfo:" $tmp/error > /dev/null 2>&1 |
| 261 | +@@ -320,6 +322,8 @@ gawk < $tmp/metrics > $tmp/variables ' |
| 262 | + function filter(string) { |
| 263 | + gsub(/"/, "\\\"", string) # escape double quotes |
| 264 | + gsub(/\\u/, "\\\\u", string) # escape backslash-u |
| 265 | ++ # replace any characters with special shell meaning |
| 266 | ++ gsub("/\\(|\\$|\\*|)|\\{|\\}\\?|`|;|!/", "-", string) |
| 267 | + gsub(/%/, "%%", string) # percent sign in printf |
| 268 | + gsub(/^\\"|\\"$/, "\"", string) # except on ends |
| 269 | + return string |
0 commit comments