sigar-test 0.7.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +201 -0
  3. data/NOTICE +117 -0
  4. data/README +2 -0
  5. data/Rakefile +105 -0
  6. data/bindings/SigarBuild.pm +301 -0
  7. data/bindings/SigarWrapper.pm +3025 -0
  8. data/bindings/ruby/extconf.rb +131 -0
  9. data/bindings/ruby/rbsigar.c +888 -0
  10. data/include/sigar.h +984 -0
  11. data/include/sigar_fileinfo.h +157 -0
  12. data/include/sigar_format.h +65 -0
  13. data/include/sigar_getline.h +18 -0
  14. data/include/sigar_log.h +80 -0
  15. data/include/sigar_private.h +429 -0
  16. data/include/sigar_ptql.h +53 -0
  17. data/include/sigar_util.h +197 -0
  18. data/src/os/aix/aix_sigar.c +2168 -0
  19. data/src/os/aix/sigar_os.h +73 -0
  20. data/src/os/darwin/Info.plist.in +27 -0
  21. data/src/os/darwin/darwin_sigar.c +3718 -0
  22. data/src/os/darwin/sigar_os.h +80 -0
  23. data/src/os/hpux/hpux_sigar.c +1361 -0
  24. data/src/os/hpux/sigar_os.h +49 -0
  25. data/src/os/linux/linux_sigar.c +2810 -0
  26. data/src/os/linux/sigar_os.h +82 -0
  27. data/src/os/solaris/get_mib2.c +321 -0
  28. data/src/os/solaris/get_mib2.h +127 -0
  29. data/src/os/solaris/kstats.c +181 -0
  30. data/src/os/solaris/procfs.c +97 -0
  31. data/src/os/solaris/sigar_os.h +224 -0
  32. data/src/os/solaris/solaris_sigar.c +2732 -0
  33. data/src/os/win32/peb.c +212 -0
  34. data/src/os/win32/sigar.rc.in +40 -0
  35. data/src/os/win32/sigar_os.h +685 -0
  36. data/src/os/win32/sigar_pdh.h +47 -0
  37. data/src/os/win32/win32_sigar.c +4109 -0
  38. data/src/sigar.c +2444 -0
  39. data/src/sigar_cache.c +253 -0
  40. data/src/sigar_fileinfo.c +815 -0
  41. data/src/sigar_format.c +696 -0
  42. data/src/sigar_getline.c +1849 -0
  43. data/src/sigar_ptql.c +1976 -0
  44. data/src/sigar_signal.c +216 -0
  45. data/src/sigar_util.c +1060 -0
  46. data/src/sigar_version.c.in +22 -0
  47. data/src/sigar_version_autoconf.c.in +22 -0
  48. data/version.properties +11 -0
  49. metadata +91 -0
data/src/sigar_ptql.c ADDED
@@ -0,0 +1,1976 @@
1
+ /*
2
+ * Copyright (c) 2006-2008 Hyperic, Inc.
3
+ * Copyright (c) 2009 SpringSource, Inc.
4
+ * Copyright (c) 2010 VMware, Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "sigar.h"
20
+ #include "sigar_private.h"
21
+ #include "sigar_util.h"
22
+ #include "sigar_ptql.h"
23
+ #include "sigar_os.h"
24
+
25
+ #include <stdio.h>
26
+
27
+ #ifdef SIGAR_HAS_PCRE
28
+ #include "pcre.h"
29
+ #endif
30
+
31
+ /* See http://gcc.gnu.org/ml/libstdc++/2002-03/msg00164.html */
32
+ #if defined(WIN32) || (defined(__hpux) && defined(SIGAR_64BIT))
33
+ #define strtoull strtoul
34
+ #elif (defined(__hpux) && !defined(SIGAR_64BIT))
35
+ #define strtoull __strtoull
36
+ #else
37
+ #include <errno.h>
38
+ #endif
39
+
40
+ #define SIGAR_CLEAR_ERRNO() errno = 0
41
+
42
+ #define strtonum_failed(src, ptr) \
43
+ ((src == ptr) || (errno == ERANGE) || (*ptr != '\0'))
44
+
45
+ typedef struct ptql_parse_branch_t ptql_parse_branch_t;
46
+ typedef struct ptql_branch_t ptql_branch_t;
47
+
48
+ /* adhere to calling convention, else risk stack corruption */
49
+ #ifdef WIN32
50
+ #define SIGAPI WINAPI
51
+ #else
52
+ #define SIGAPI
53
+ #endif
54
+
55
+ typedef int (SIGAPI *ptql_get_t)(sigar_t *sigar, sigar_pid_t pid, void *data);
56
+ typedef int (*ptql_branch_init_t)(ptql_parse_branch_t *parsed, ptql_branch_t *branch,
57
+ sigar_ptql_error_t *error);
58
+
59
+ typedef int (*ptql_op_ui64_t)(ptql_branch_t *branch,
60
+ sigar_uint64_t haystack,
61
+ sigar_uint64_t needle);
62
+
63
+ typedef int (*ptql_op_ui32_t)(ptql_branch_t *branch,
64
+ sigar_uint32_t haystack,
65
+ sigar_uint32_t needle);
66
+
67
+ typedef int (*ptql_op_dbl_t)(ptql_branch_t *branch,
68
+ double haystack,
69
+ double needle);
70
+
71
+ typedef int (*ptql_op_str_t)(ptql_branch_t *branch,
72
+ char *haystack,
73
+ char *needle);
74
+
75
+ typedef int (*ptql_op_chr_t)(ptql_branch_t *branch,
76
+ char haystack,
77
+ char needle);
78
+
79
+ typedef enum {
80
+ PTQL_VALUE_TYPE_UI64,
81
+ PTQL_VALUE_TYPE_UI32,
82
+ PTQL_VALUE_TYPE_DBL,
83
+ PTQL_VALUE_TYPE_CHR,
84
+ PTQL_VALUE_TYPE_STR,
85
+ PTQL_VALUE_TYPE_ANY
86
+ } ptql_value_type_t;
87
+
88
+ typedef enum {
89
+ PTQL_OP_EQ,
90
+ PTQL_OP_NE,
91
+ PTQL_OP_GT,
92
+ PTQL_OP_GE,
93
+ PTQL_OP_LT,
94
+ PTQL_OP_LE,
95
+ #define PTQL_OP_MAX_NSTR PTQL_OP_LE
96
+ PTQL_OP_EW, /* rest are string only */
97
+ PTQL_OP_SW,
98
+ PTQL_OP_RE,
99
+ PTQL_OP_CT,
100
+ PTQL_OP_MAX
101
+ } ptql_op_name_t;
102
+
103
+ #define PTQL_OP_FLAG_PARENT 1
104
+ #define PTQL_OP_FLAG_REF 2
105
+ #define PTQL_OP_FLAG_GLOB 4
106
+ #define PTQL_OP_FLAG_PID 8
107
+ #define PTQL_OP_FLAG_ICASE 16
108
+
109
+ struct ptql_parse_branch_t {
110
+ char *name;
111
+ char *attr;
112
+ char *op;
113
+ char *value;
114
+ unsigned int op_flags;
115
+ };
116
+
117
+ typedef struct {
118
+ char *name;
119
+ ptql_get_t get;
120
+ size_t offset;
121
+ unsigned int data_size;
122
+ ptql_value_type_t type;
123
+ ptql_branch_init_t init;
124
+ } ptql_lookup_t;
125
+
126
+ #define DATA_PTR(branch) \
127
+ ((char *)branch->data.ptr + branch->lookup->offset)
128
+
129
+ #define IS_ICASE(branch) \
130
+ (branch->op_flags & PTQL_OP_FLAG_ICASE)
131
+
132
+ #define branch_strcmp(branch, s1, s2) \
133
+ (IS_ICASE(branch) ? strcasecmp(s1, s2) : strcmp(s1, s2))
134
+
135
+ #define branch_strncmp(branch, s1, s2, n) \
136
+ (IS_ICASE(branch) ? strncasecmp(s1, s2, n) : strncmp(s1, s2, n))
137
+
138
+ #define branch_strEQ(branch, s1, s2) \
139
+ (branch_strcmp(branch, s1, s2) == 0)
140
+
141
+ #define branch_strnEQ(branch, s1, s2, n) \
142
+ (branch_strncmp(branch, s1, s2, n) == 0)
143
+
144
+ #define branch_strstr(branch, s1, s2) \
145
+ (IS_ICASE(branch) ? sigar_strcasestr(s1, s2) : strstr(s1, s2))
146
+
147
+ #define IS_PID_SERVICE_QUERY(branch) \
148
+ (branch->flags >= PTQL_PID_SERVICE_NAME)
149
+
150
+ static void data_free(void *data)
151
+ {
152
+ free(data);
153
+ }
154
+
155
+ typedef union {
156
+ sigar_pid_t pid;
157
+ sigar_uint64_t ui64;
158
+ sigar_uint32_t ui32;
159
+ double dbl;
160
+ char chr[4];
161
+ char *str;
162
+ void *ptr;
163
+ } any_value_t;
164
+
165
+ struct ptql_branch_t {
166
+ ptql_lookup_t *lookup;
167
+ any_value_t data;
168
+ unsigned int data_size;
169
+ void (*data_free)(void *);
170
+ unsigned int flags;
171
+ unsigned int op_flags;
172
+ ptql_op_name_t op_name;
173
+ union {
174
+ ptql_op_ui64_t ui64;
175
+ ptql_op_ui32_t ui32;
176
+ ptql_op_dbl_t dbl;
177
+ ptql_op_chr_t chr;
178
+ ptql_op_str_t str;
179
+ } match;
180
+ any_value_t value;
181
+ void (*value_free)(void *);
182
+ };
183
+
184
+ typedef struct {
185
+ char *name;
186
+ ptql_lookup_t *members;
187
+ } ptql_entry_t;
188
+
189
+ typedef struct {
190
+ unsigned long number;
191
+ unsigned long size;
192
+ ptql_branch_t *data;
193
+ } ptql_branch_list_t;
194
+
195
+ struct sigar_ptql_query_t {
196
+ ptql_branch_list_t branches;
197
+ #ifdef PTQL_DEBUG
198
+ char *ptql;
199
+ #endif
200
+ };
201
+
202
+ /* XXX optimize */
203
+ static ptql_op_name_t ptql_op_code_get(char *op)
204
+ {
205
+ if (strEQ(op, "eq")) {
206
+ return PTQL_OP_EQ;
207
+ }
208
+ else if (strEQ(op, "ne")) {
209
+ return PTQL_OP_NE;
210
+ }
211
+ else if (strEQ(op, "gt")) {
212
+ return PTQL_OP_GT;
213
+ }
214
+ else if (strEQ(op, "ge")) {
215
+ return PTQL_OP_GE;
216
+ }
217
+ else if (strEQ(op, "lt")) {
218
+ return PTQL_OP_LT;
219
+ }
220
+ else if (strEQ(op, "le")) {
221
+ return PTQL_OP_LE;
222
+ }
223
+ else if (strEQ(op, "ew")) {
224
+ return PTQL_OP_EW;
225
+ }
226
+ else if (strEQ(op, "sw")) {
227
+ return PTQL_OP_SW;
228
+ }
229
+ else if (strEQ(op, "re")) {
230
+ return PTQL_OP_RE;
231
+ }
232
+ else if (strEQ(op, "ct")) {
233
+ return PTQL_OP_CT;
234
+ }
235
+ else {
236
+ return PTQL_OP_MAX;
237
+ }
238
+ }
239
+
240
+ static int ptql_op_ui64_eq(ptql_branch_t *branch,
241
+ sigar_uint64_t haystack, sigar_uint64_t needle)
242
+ {
243
+ return haystack == needle;
244
+ }
245
+
246
+ static int ptql_op_ui64_ne(ptql_branch_t *branch,
247
+ sigar_uint64_t haystack, sigar_uint64_t needle)
248
+ {
249
+ return haystack != needle;
250
+ }
251
+
252
+ static int ptql_op_ui64_gt(ptql_branch_t *branch,
253
+ sigar_uint64_t haystack, sigar_uint64_t needle)
254
+ {
255
+ return haystack > needle;
256
+ }
257
+
258
+ static int ptql_op_ui64_ge(ptql_branch_t *branch,
259
+ sigar_uint64_t haystack, sigar_uint64_t needle)
260
+ {
261
+ return haystack >= needle;
262
+ }
263
+
264
+ static int ptql_op_ui64_lt(ptql_branch_t *branch,
265
+ sigar_uint64_t haystack, sigar_uint64_t needle)
266
+ {
267
+ return haystack < needle;
268
+ }
269
+
270
+ static int ptql_op_ui64_le(ptql_branch_t *branch,
271
+ sigar_uint64_t haystack, sigar_uint64_t needle)
272
+ {
273
+ return haystack <= needle;
274
+ }
275
+
276
+ static ptql_op_ui64_t ptql_op_ui64[] = {
277
+ ptql_op_ui64_eq,
278
+ ptql_op_ui64_ne,
279
+ ptql_op_ui64_gt,
280
+ ptql_op_ui64_ge,
281
+ ptql_op_ui64_lt,
282
+ ptql_op_ui64_le
283
+ };
284
+
285
+ static int ptql_op_ui32_eq(ptql_branch_t *branch,
286
+ sigar_uint32_t haystack, sigar_uint32_t needle)
287
+ {
288
+ return haystack == needle;
289
+ }
290
+
291
+ static int ptql_op_ui32_ne(ptql_branch_t *branch,
292
+ sigar_uint32_t haystack, sigar_uint32_t needle)
293
+ {
294
+ return haystack != needle;
295
+ }
296
+
297
+ static int ptql_op_ui32_gt(ptql_branch_t *branch,
298
+ sigar_uint32_t haystack, sigar_uint32_t needle)
299
+ {
300
+ return haystack > needle;
301
+ }
302
+
303
+ static int ptql_op_ui32_ge(ptql_branch_t *branch,
304
+ sigar_uint32_t haystack, sigar_uint32_t needle)
305
+ {
306
+ return haystack >= needle;
307
+ }
308
+
309
+ static int ptql_op_ui32_lt(ptql_branch_t *branch,
310
+ sigar_uint32_t haystack, sigar_uint32_t needle)
311
+ {
312
+ return haystack < needle;
313
+ }
314
+
315
+ static int ptql_op_ui32_le(ptql_branch_t *branch,
316
+ sigar_uint32_t haystack, sigar_uint32_t needle)
317
+ {
318
+ return haystack <= needle;
319
+ }
320
+
321
+ static ptql_op_ui32_t ptql_op_ui32[] = {
322
+ ptql_op_ui32_eq,
323
+ ptql_op_ui32_ne,
324
+ ptql_op_ui32_gt,
325
+ ptql_op_ui32_ge,
326
+ ptql_op_ui32_lt,
327
+ ptql_op_ui32_le
328
+ };
329
+
330
+ static int ptql_op_dbl_eq(ptql_branch_t *branch,
331
+ double haystack, double needle)
332
+ {
333
+ return haystack == needle;
334
+ }
335
+
336
+ static int ptql_op_dbl_ne(ptql_branch_t *branch,
337
+ double haystack, double needle)
338
+ {
339
+ return haystack != needle;
340
+ }
341
+
342
+ static int ptql_op_dbl_gt(ptql_branch_t *branch,
343
+ double haystack, double needle)
344
+ {
345
+ return haystack > needle;
346
+ }
347
+
348
+ static int ptql_op_dbl_ge(ptql_branch_t *branch,
349
+ double haystack, double needle)
350
+ {
351
+ return haystack >= needle;
352
+ }
353
+
354
+ static int ptql_op_dbl_lt(ptql_branch_t *branch,
355
+ double haystack, double needle)
356
+ {
357
+ return haystack < needle;
358
+ }
359
+
360
+ static int ptql_op_dbl_le(ptql_branch_t *branch,
361
+ double haystack, double needle)
362
+ {
363
+ return haystack <= needle;
364
+ }
365
+
366
+ static ptql_op_dbl_t ptql_op_dbl[] = {
367
+ ptql_op_dbl_eq,
368
+ ptql_op_dbl_ne,
369
+ ptql_op_dbl_gt,
370
+ ptql_op_dbl_ge,
371
+ ptql_op_dbl_lt,
372
+ ptql_op_dbl_le
373
+ };
374
+
375
+ static int ptql_op_str_eq(ptql_branch_t *branch,
376
+ char *haystack, char *needle)
377
+ {
378
+ return branch_strEQ(branch, haystack, needle);
379
+ }
380
+
381
+ static int ptql_op_str_ne(ptql_branch_t *branch,
382
+ char *haystack, char *needle)
383
+ {
384
+ return !branch_strEQ(branch, haystack, needle);
385
+ }
386
+
387
+ static int ptql_op_str_gt(ptql_branch_t *branch,
388
+ char *haystack, char *needle)
389
+ {
390
+ return branch_strcmp(branch, haystack, needle) > 0;
391
+ }
392
+
393
+ static int ptql_op_str_ge(ptql_branch_t *branch,
394
+ char *haystack, char *needle)
395
+ {
396
+ return branch_strcmp(branch, haystack, needle) >= 0;
397
+ }
398
+
399
+ static int ptql_op_str_lt(ptql_branch_t *branch,
400
+ char *haystack, char *needle)
401
+ {
402
+ return branch_strcmp(branch, haystack, needle) < 0;
403
+ }
404
+
405
+ static int ptql_op_str_le(ptql_branch_t *branch,
406
+ char *haystack, char *needle)
407
+ {
408
+ return branch_strcmp(branch, haystack, needle) <= 0;
409
+ }
410
+
411
+ static int ptql_op_str_ew(ptql_branch_t *branch,
412
+ char *haystack, char *needle)
413
+ {
414
+ int nlen = strlen(needle);
415
+ int hlen = strlen(haystack);
416
+ int diff = hlen - nlen;
417
+ if (diff < 0) {
418
+ return 0;
419
+ }
420
+ return branch_strnEQ(branch, haystack + diff, needle, nlen);
421
+ }
422
+
423
+ static int ptql_op_str_sw(ptql_branch_t *branch,
424
+ char *haystack, char *needle)
425
+ {
426
+ return branch_strnEQ(branch, haystack, needle, strlen(needle));
427
+ }
428
+
429
+ static int ptql_op_str_re(ptql_branch_t *branch,
430
+ char *haystack, char *needle)
431
+ {
432
+ #ifdef SIGAR_HAS_PCRE
433
+ pcre *re = (pcre *)branch->value.ptr;
434
+ int len = strlen(haystack);
435
+ int rc =
436
+ pcre_exec(re, NULL, haystack, len, 0, 0, NULL, 0);
437
+ return rc >= 0;
438
+ #else
439
+ return 0;
440
+ #endif
441
+ }
442
+
443
+ static int ptql_op_str_ct(ptql_branch_t *branch,
444
+ char *haystack, char *needle)
445
+ {
446
+ return branch_strstr(branch, haystack, needle) != NULL;
447
+ }
448
+
449
+ static ptql_op_str_t ptql_op_str[] = {
450
+ ptql_op_str_eq,
451
+ ptql_op_str_ne,
452
+ ptql_op_str_gt,
453
+ ptql_op_str_ge,
454
+ ptql_op_str_lt,
455
+ ptql_op_str_le,
456
+ ptql_op_str_ew,
457
+ ptql_op_str_sw,
458
+ ptql_op_str_re,
459
+ ptql_op_str_ct
460
+ };
461
+
462
+ static int ptql_op_chr_eq(ptql_branch_t *branch,
463
+ char haystack, char needle)
464
+ {
465
+ return haystack == needle;
466
+ }
467
+
468
+ static int ptql_op_chr_ne(ptql_branch_t *branch,
469
+ char haystack, char needle)
470
+ {
471
+ return haystack != needle;
472
+ }
473
+
474
+ static int ptql_op_chr_gt(ptql_branch_t *branch,
475
+ char haystack, char needle)
476
+ {
477
+ return haystack > needle;
478
+ }
479
+
480
+ static int ptql_op_chr_ge(ptql_branch_t *branch,
481
+ char haystack, char needle)
482
+ {
483
+ return haystack >= needle;
484
+ }
485
+
486
+ static int ptql_op_chr_lt(ptql_branch_t *branch,
487
+ char haystack, char needle)
488
+ {
489
+ return haystack < needle;
490
+ }
491
+
492
+ static int ptql_op_chr_le(ptql_branch_t *branch,
493
+ char haystack, char needle)
494
+ {
495
+ return haystack <= needle;
496
+ }
497
+
498
+ static ptql_op_chr_t ptql_op_chr[] = {
499
+ ptql_op_chr_eq,
500
+ ptql_op_chr_ne,
501
+ ptql_op_chr_gt,
502
+ ptql_op_chr_ge,
503
+ ptql_op_chr_lt,
504
+ ptql_op_chr_le
505
+ };
506
+
507
+ #define PTQL_BRANCH_LIST_MAX 3
508
+
509
+ #define PTQL_BRANCH_LIST_GROW(branches) \
510
+ if ((branches)->number >= (branches)->size) { \
511
+ ptql_branch_list_grow(branches); \
512
+ }
513
+
514
+ static int ptql_branch_list_create(ptql_branch_list_t *branches)
515
+ {
516
+ branches->number = 0;
517
+ branches->size = PTQL_BRANCH_LIST_MAX;
518
+ branches->data = malloc(sizeof(*(branches->data)) *
519
+ branches->size);
520
+
521
+ return SIGAR_OK;
522
+ }
523
+
524
+ static int ptql_branch_list_grow(ptql_branch_list_t *branches)
525
+ {
526
+ branches->data =
527
+ realloc(branches->data,
528
+ sizeof(*(branches->data)) *
529
+ (branches->size + PTQL_BRANCH_LIST_MAX));
530
+ branches->size += PTQL_BRANCH_LIST_MAX;
531
+
532
+ return SIGAR_OK;
533
+ }
534
+
535
+ static int ptql_branch_list_destroy(ptql_branch_list_t *branches)
536
+ {
537
+ if (branches->size) {
538
+ int i;
539
+
540
+ for (i=0; i<branches->number; i++) {
541
+ ptql_branch_t *branch =
542
+ &branches->data[i];
543
+
544
+ if (branch->data_size && branch->data.ptr) {
545
+ branch->data_free(branch->data.ptr);
546
+ }
547
+
548
+ if (branch->lookup &&
549
+ ((branch->lookup->type == PTQL_VALUE_TYPE_STR) ||
550
+ (branch->lookup->type == PTQL_VALUE_TYPE_ANY)) &&
551
+ !(branch->op_flags & PTQL_OP_FLAG_REF))
552
+ {
553
+ if (branch->value.str) {
554
+ branch->value_free(branch->value.str);
555
+ }
556
+ }
557
+ }
558
+
559
+ free(branches->data);
560
+ branches->number = branches->size = 0;
561
+ }
562
+
563
+ return SIGAR_OK;
564
+ }
565
+
566
+ #ifdef WIN32
567
+ #define vsnprintf _vsnprintf
568
+ #endif
569
+
570
+ #define PTQL_ERRNAN \
571
+ ptql_error(error, "Query value '%s' is not a number", parsed->value)
572
+
573
+ static int ptql_error(sigar_ptql_error_t *error, const char *format, ...)
574
+ {
575
+ va_list args;
576
+
577
+ if (error != NULL) {
578
+ va_start(args, format);
579
+ vsnprintf(error->message, sizeof(error->message), format, args);
580
+ va_end(args);
581
+ }
582
+
583
+ return SIGAR_PTQL_MALFORMED_QUERY;
584
+ }
585
+
586
+ static int ptql_branch_init_any(ptql_parse_branch_t *parsed,
587
+ ptql_branch_t *branch,
588
+ sigar_ptql_error_t *error)
589
+ {
590
+ branch->data.str = sigar_strdup(parsed->attr);
591
+ branch->data_size = strlen(parsed->attr);
592
+ return SIGAR_OK;
593
+ }
594
+
595
+ static int ptql_str_match(sigar_t *sigar, ptql_branch_t *branch, char *value)
596
+ {
597
+ if (!branch->value.str) {
598
+ return 0;
599
+ }
600
+ #ifndef SIGAR_HAS_PCRE
601
+ if (branch->op_name == PTQL_OP_RE) {
602
+ if (sigar->ptql_re_impl) {
603
+ return sigar->ptql_re_impl(sigar->ptql_re_data,
604
+ value,
605
+ branch->value.str);
606
+ }
607
+ else {
608
+ return 0;
609
+ }
610
+ }
611
+ #endif
612
+ return branch->match.str(branch,
613
+ value,
614
+ branch->value.str);
615
+ }
616
+
617
+ static int ptql_branch_match(ptql_branch_t *branch)
618
+ {
619
+ switch (branch->lookup->type) {
620
+ case PTQL_VALUE_TYPE_UI64:
621
+ return branch->match.ui64(branch,
622
+ *(sigar_uint64_t *)DATA_PTR(branch),
623
+ branch->value.ui64);
624
+ case PTQL_VALUE_TYPE_UI32:
625
+ return branch->match.ui32(branch,
626
+ *(sigar_uint32_t *)DATA_PTR(branch),
627
+ branch->value.ui32);
628
+ case PTQL_VALUE_TYPE_DBL:
629
+ return branch->match.dbl(branch,
630
+ *(double *)DATA_PTR(branch),
631
+ branch->value.dbl);
632
+ case PTQL_VALUE_TYPE_CHR:
633
+ return branch->match.chr(branch,
634
+ *(char *)DATA_PTR(branch),
635
+ branch->value.chr[0]);
636
+ case PTQL_VALUE_TYPE_STR:
637
+ case PTQL_VALUE_TYPE_ANY:
638
+ if (!branch->value.str) {
639
+ return 0;
640
+ }
641
+ return branch->match.str(branch,
642
+ (char *)DATA_PTR(branch),
643
+ branch->value.str);
644
+ default:
645
+ return 0;
646
+ }
647
+ }
648
+
649
+ static int ptql_branch_match_ref(ptql_branch_t *branch, ptql_branch_t *ref)
650
+ {
651
+ switch (branch->lookup->type) {
652
+ case PTQL_VALUE_TYPE_UI64:
653
+ return branch->match.ui64(branch,
654
+ *(sigar_uint64_t *)DATA_PTR(branch),
655
+ *(sigar_uint64_t *)DATA_PTR(ref));
656
+ case PTQL_VALUE_TYPE_UI32:
657
+ return branch->match.ui32(branch,
658
+ *(sigar_uint32_t *)DATA_PTR(branch),
659
+ *(sigar_uint32_t *)DATA_PTR(ref));
660
+ case PTQL_VALUE_TYPE_DBL:
661
+ return branch->match.dbl(branch,
662
+ *(double *)DATA_PTR(branch),
663
+ *(double *)DATA_PTR(ref));
664
+ case PTQL_VALUE_TYPE_CHR:
665
+ return branch->match.chr(branch,
666
+ *(char *)DATA_PTR(branch),
667
+ *(char *)DATA_PTR(ref));
668
+ case PTQL_VALUE_TYPE_STR:
669
+ case PTQL_VALUE_TYPE_ANY:
670
+ return branch->match.str(branch,
671
+ (char *)DATA_PTR(branch),
672
+ (char *)DATA_PTR(ref));
673
+ default:
674
+ return 0;
675
+ }
676
+ }
677
+
678
+ enum {
679
+ PTQL_PID_PID,
680
+ PTQL_PID_FILE,
681
+ PTQL_PID_SUDO_FILE,
682
+ PTQL_PID_TCP_PORT,
683
+ PTQL_PID_UDP_PORT,
684
+ PTQL_PID_SERVICE_NAME,
685
+ PTQL_PID_SERVICE_DISPLAY,
686
+ PTQL_PID_SERVICE_PATH,
687
+ PTQL_PID_SERVICE_EXE,
688
+ PTQL_PID_SERVICE_PID
689
+ };
690
+
691
+ #ifdef SIGAR_64BIT
692
+
693
+ #define str2pid(value, ptr) strtoull(value, &ptr, 10)
694
+
695
+ #define pid_branch_match(branch, pid, match_pid) \
696
+ ptql_op_ui64[branch->op_name](branch, pid, match_pid)
697
+
698
+ #else
699
+
700
+ #define str2pid(value, ptr) strtoul(value, &ptr, 10)
701
+
702
+ #define pid_branch_match(branch, pid, match_pid) \
703
+ ptql_op_ui32[branch->op_name](branch, pid, match_pid)
704
+
705
+ #endif
706
+
707
+ #ifndef WIN32
708
+ #include <sys/stat.h>
709
+ int sigar_sudo_file2str(const char *fname, char *buffer, int buflen)
710
+ {
711
+ FILE *fp;
712
+ struct stat sb;
713
+
714
+ if (stat(fname, &sb) < 0) {
715
+ return errno;
716
+ }
717
+ if (sb.st_size > buflen) {
718
+ return ENOMEM;
719
+ }
720
+ snprintf(buffer, buflen, "sudo cat %s", fname);
721
+ if (!(fp = popen(buffer, "r"))) {
722
+ return errno;
723
+ }
724
+ (void)fgets(buffer, buflen, fp);
725
+ pclose(fp);
726
+
727
+ return SIGAR_OK;
728
+ }
729
+ #endif
730
+
731
+ static int ptql_branch_init_service(ptql_parse_branch_t *parsed,
732
+ ptql_branch_t *branch,
733
+ sigar_ptql_error_t *error)
734
+ {
735
+ branch->op_flags |= PTQL_OP_FLAG_PID;
736
+
737
+ if (strEQ(parsed->attr, "Name")) {
738
+ branch->flags = PTQL_PID_SERVICE_NAME;
739
+ }
740
+ else if (strEQ(parsed->attr, "DisplayName")) {
741
+ branch->flags = PTQL_PID_SERVICE_DISPLAY;
742
+ }
743
+ else if (strEQ(parsed->attr, "Path")) {
744
+ branch->flags = PTQL_PID_SERVICE_PATH;
745
+ }
746
+ else if (strEQ(parsed->attr, "Exe")) {
747
+ /* basename of Path */
748
+ branch->flags = PTQL_PID_SERVICE_EXE;
749
+ }
750
+ else if (strEQ(parsed->attr, "Pid")) {
751
+ branch->flags = PTQL_PID_SERVICE_PID;
752
+ }
753
+ else {
754
+ return ptql_error(error, "Unsupported %s attribute: %s",
755
+ parsed->name, parsed->attr);
756
+ }
757
+
758
+ #ifdef WIN32
759
+ branch->data.str = sigar_strdup(parsed->value);
760
+ branch->data_size = strlen(parsed->value);
761
+ #endif
762
+ return SIGAR_OK;
763
+ }
764
+
765
+ static int ptql_branch_init_pid(ptql_parse_branch_t *parsed,
766
+ ptql_branch_t *branch,
767
+ sigar_ptql_error_t *error)
768
+ {
769
+ int use_sudo = 0;
770
+ branch->op_flags |= PTQL_OP_FLAG_PID;
771
+
772
+ if (strEQ(parsed->attr, "Pid")) {
773
+ branch->flags = PTQL_PID_PID;
774
+ if (strEQ(parsed->value, "$$")) {
775
+ branch->data.pid = getpid();
776
+ }
777
+ else {
778
+ char *ptr;
779
+ SIGAR_CLEAR_ERRNO();
780
+ branch->data.pid = str2pid(parsed->value, ptr);
781
+ if (strtonum_failed(parsed->value, ptr)) {
782
+ return PTQL_ERRNAN;
783
+ }
784
+ }
785
+ return SIGAR_OK;
786
+ }
787
+ else if (strEQ(parsed->attr, "PidFile") ||
788
+ (use_sudo = strEQ(parsed->attr, "SudoPidFile")))
789
+ {
790
+ branch->flags = use_sudo ? PTQL_PID_SUDO_FILE : PTQL_PID_FILE;
791
+ branch->data.str = sigar_strdup(parsed->value);
792
+ branch->data_size = strlen(parsed->value);
793
+ return SIGAR_OK;
794
+ }
795
+
796
+ return ptql_error(error, "Unsupported %s attribute: %s",
797
+ parsed->name, parsed->attr);
798
+ }
799
+
800
+ #ifdef WIN32
801
+ #define QUERY_SC_SIZE 8192
802
+
803
+ static int ptql_service_query_config(SC_HANDLE scm_handle,
804
+ char *name,
805
+ LPQUERY_SERVICE_CONFIG config)
806
+ {
807
+ int status;
808
+ DWORD bytes;
809
+ SC_HANDLE handle =
810
+ OpenService(scm_handle, name, SERVICE_QUERY_CONFIG);
811
+
812
+ if (!handle) {
813
+ return GetLastError();
814
+ }
815
+
816
+ if (QueryServiceConfig(handle, config, QUERY_SC_SIZE, &bytes)) {
817
+ status = SIGAR_OK;
818
+ }
819
+ else {
820
+ status = GetLastError();
821
+ }
822
+
823
+ CloseServiceHandle(handle);
824
+ return status;
825
+ }
826
+
827
+ static int sigar_services_walk(sigar_services_walker_t *walker,
828
+ ptql_branch_t *branch)
829
+ {
830
+ sigar_services_status_t ss;
831
+ char buffer[QUERY_SC_SIZE];
832
+ char exe[SIGAR_CMDLINE_MAX];
833
+ LPQUERY_SERVICE_CONFIG config = (LPQUERY_SERVICE_CONFIG)buffer;
834
+ DWORD i, status;
835
+
836
+ SIGAR_ZERO(&ss);
837
+ status = sigar_services_status_get(&ss, walker->flags);
838
+ if (status != SIGAR_OK) {
839
+ return status;
840
+ }
841
+ for (i=0; i<ss.count; i++) {
842
+ sigar_pid_t service_pid = 0;
843
+ int status;
844
+ char *value = NULL;
845
+ char *name = ss.services[i].lpServiceName;
846
+
847
+ if (branch == NULL) {
848
+ /* no query, return all */
849
+ if (walker->add_service(walker, name) != SIGAR_OK) {
850
+ break;
851
+ }
852
+ continue;
853
+ }
854
+
855
+ switch (branch->flags) {
856
+ case PTQL_PID_SERVICE_DISPLAY:
857
+ value = ss.services[i].lpDisplayName;
858
+ break;
859
+ case PTQL_PID_SERVICE_PATH:
860
+ case PTQL_PID_SERVICE_EXE:
861
+ status = ptql_service_query_config(ss.handle, name, config);
862
+ if (status == SIGAR_OK) {
863
+ if (branch->flags == PTQL_PID_SERVICE_EXE) {
864
+ value =
865
+ sigar_service_exe_get(config->lpBinaryPathName,
866
+ exe, 1);
867
+ }
868
+ else {
869
+ value = config->lpBinaryPathName;
870
+ }
871
+ }
872
+ else {
873
+ continue;
874
+ }
875
+ break;
876
+ case PTQL_PID_SERVICE_PID:
877
+ sigar_service_pid_get(walker->sigar,
878
+ name,
879
+ &service_pid);
880
+ break;
881
+ case PTQL_PID_SERVICE_NAME:
882
+ default:
883
+ value = name;
884
+ break;
885
+ }
886
+
887
+ if ((value && ptql_str_match(walker->sigar, branch, value)) ||
888
+ (service_pid &&
889
+ pid_branch_match(branch, service_pid, atoi(branch->data.str))))
890
+ {
891
+ if (walker->add_service(walker, name) != SIGAR_OK) {
892
+ break;
893
+ }
894
+ }
895
+ }
896
+
897
+ sigar_services_status_close(&ss);
898
+
899
+ return SIGAR_OK;
900
+ }
901
+
902
+ static int ptql_pid_service_add(sigar_services_walker_t *walker,
903
+ char *name)
904
+ {
905
+ sigar_pid_t service_pid;
906
+ sigar_proc_list_t *proclist =
907
+ (sigar_proc_list_t *)walker->data;
908
+ int status =
909
+ sigar_service_pid_get(walker->sigar,
910
+ name,
911
+ &service_pid);
912
+
913
+ if (status == SIGAR_OK) {
914
+ SIGAR_PROC_LIST_GROW(proclist);
915
+ proclist->data[proclist->number++] = service_pid;
916
+ }
917
+
918
+ return SIGAR_OK;
919
+ }
920
+
921
+ static int ptql_pid_service_list_get(sigar_t *sigar,
922
+ ptql_branch_t *branch,
923
+ sigar_proc_list_t *proclist)
924
+ {
925
+ sigar_services_walker_t walker;
926
+ walker.sigar = sigar;
927
+ walker.flags = SERVICE_ACTIVE;
928
+ walker.data = proclist;
929
+ walker.add_service = ptql_pid_service_add;
930
+
931
+ return sigar_services_walk(&walker, branch);
932
+ }
933
+
934
+ int sigar_services_query(char *ptql,
935
+ sigar_ptql_error_t *error,
936
+ sigar_services_walker_t *walker)
937
+ {
938
+ int status;
939
+ sigar_ptql_query_t *query;
940
+
941
+ if (ptql == NULL) {
942
+ return sigar_services_walk(walker, NULL);
943
+ }
944
+
945
+ status = sigar_ptql_query_create(&query, (char *)ptql, error);
946
+ if (status != SIGAR_OK) {
947
+ return status;
948
+ }
949
+
950
+ if (query->branches.number == 1) {
951
+ ptql_branch_t *branch = &query->branches.data[0];
952
+
953
+ if (IS_PID_SERVICE_QUERY(branch)) {
954
+ status = sigar_services_walk(walker, branch);
955
+ }
956
+ else {
957
+ ptql_error(error, "Invalid Service query: %s", ptql);
958
+ status = SIGAR_PTQL_MALFORMED_QUERY;
959
+ }
960
+ }
961
+ else {
962
+ ptql_error(error, "Too many queries (%d), must be (1)",
963
+ query->branches.number);
964
+ status = SIGAR_PTQL_MALFORMED_QUERY;
965
+ }
966
+
967
+ sigar_ptql_query_destroy(query);
968
+
969
+ return status;
970
+ }
971
+ #endif
972
+
973
+ static int ptql_pid_port_get(sigar_t *sigar,
974
+ ptql_branch_t *branch,
975
+ sigar_pid_t *pid)
976
+ {
977
+ unsigned long port =
978
+ branch->data.ui32;
979
+ int status;
980
+ int proto =
981
+ branch->flags == PTQL_PID_UDP_PORT ?
982
+ SIGAR_NETCONN_UDP : SIGAR_NETCONN_TCP;
983
+
984
+ status =
985
+ sigar_proc_port_get(sigar, proto, port, pid);
986
+
987
+ return status;
988
+ }
989
+
990
+ static int ptql_pid_get(sigar_t *sigar,
991
+ ptql_branch_t *branch,
992
+ sigar_pid_t *pid)
993
+ {
994
+ if ((branch->flags == PTQL_PID_FILE) ||
995
+ (branch->flags == PTQL_PID_SUDO_FILE))
996
+ {
997
+ char *ptr, buffer[SIGAR_PATH_MAX+1];
998
+ const char *fname = (const char *)branch->data.str;
999
+ int status, len = sizeof(buffer)-1;
1000
+
1001
+ if (branch->flags == PTQL_PID_FILE) {
1002
+ status = sigar_file2str(fname, buffer, len);
1003
+ }
1004
+ else {
1005
+ #ifdef WIN32
1006
+ return SIGAR_ENOTIMPL;
1007
+ #else
1008
+ status = sigar_sudo_file2str(fname, buffer, len);
1009
+ #endif
1010
+ }
1011
+ if (status != SIGAR_OK) {
1012
+ return status;
1013
+ }
1014
+ SIGAR_CLEAR_ERRNO();
1015
+ *pid = str2pid(buffer, ptr);
1016
+ if ((buffer == ptr) || (errno == ERANGE)) {
1017
+ return errno;
1018
+ }
1019
+ }
1020
+ else if (branch->flags == PTQL_PID_SERVICE_NAME) {
1021
+ #ifdef WIN32
1022
+ int status =
1023
+ sigar_service_pid_get(sigar,
1024
+ branch->data.str, pid);
1025
+ if (status != SIGAR_OK) {
1026
+ return status;
1027
+ }
1028
+ #else
1029
+ return SIGAR_ENOTIMPL;
1030
+ #endif
1031
+ }
1032
+ else if ((branch->flags == PTQL_PID_UDP_PORT) ||
1033
+ (branch->flags == PTQL_PID_TCP_PORT))
1034
+ {
1035
+ int status = ptql_pid_port_get(sigar, branch, pid);
1036
+ if (status != SIGAR_OK) {
1037
+ return status;
1038
+ }
1039
+ }
1040
+ else {
1041
+ *pid = branch->data.pid;
1042
+ }
1043
+
1044
+ return SIGAR_OK;
1045
+ }
1046
+
1047
+ static int ptql_pid_list_get(sigar_t *sigar,
1048
+ ptql_branch_t *branch,
1049
+ sigar_proc_list_t *proclist)
1050
+ {
1051
+ int status, i;
1052
+ sigar_pid_t match_pid;
1053
+
1054
+ if (IS_PID_SERVICE_QUERY(branch)) {
1055
+ if ((branch->flags > PTQL_PID_SERVICE_NAME) ||
1056
+ (branch->op_name != PTQL_OP_EQ))
1057
+ {
1058
+ #ifdef WIN32
1059
+ return ptql_pid_service_list_get(sigar, branch, proclist);
1060
+ #else
1061
+ return SIGAR_OK; /* no matches */
1062
+ #endif
1063
+ }
1064
+ }
1065
+
1066
+ status = ptql_pid_get(sigar, branch, &match_pid);
1067
+
1068
+ if (status != SIGAR_OK) {
1069
+ /* XXX treated as non-match but would be nice to propagate */
1070
+ return SIGAR_OK;
1071
+ }
1072
+
1073
+ status = sigar_proc_list_get(sigar, NULL);
1074
+ if (status != SIGAR_OK) {
1075
+ return status;
1076
+ }
1077
+ for (i=0; i<sigar->pids->number; i++) {
1078
+ sigar_pid_t pid = sigar->pids->data[i];
1079
+ if (pid_branch_match(branch, pid, match_pid)) {
1080
+ SIGAR_PROC_LIST_GROW(proclist);
1081
+ proclist->data[proclist->number++] = pid;
1082
+ }
1083
+ }
1084
+
1085
+ return SIGAR_OK;
1086
+ }
1087
+
1088
+ static int SIGAPI ptql_pid_match(sigar_t *sigar,
1089
+ sigar_pid_t pid,
1090
+ void *data)
1091
+ {
1092
+ /* query already used to filter proc_list */
1093
+ return SIGAR_OK;
1094
+ }
1095
+
1096
+ static int ptql_args_branch_init(ptql_parse_branch_t *parsed,
1097
+ ptql_branch_t *branch,
1098
+ sigar_ptql_error_t *error)
1099
+ {
1100
+ if (strEQ(parsed->attr, "*")) {
1101
+ branch->op_flags |= PTQL_OP_FLAG_GLOB;
1102
+ }
1103
+ else {
1104
+ char *end;
1105
+
1106
+ SIGAR_CLEAR_ERRNO();
1107
+ branch->data.ui32 =
1108
+ strtol(parsed->attr, &end, 10);
1109
+
1110
+ if (strtonum_failed(parsed->attr, end)) {
1111
+ /* conversion failed */
1112
+ return ptql_error(error, "%s is not a number", parsed->attr);
1113
+ }
1114
+ }
1115
+ return SIGAR_OK;
1116
+ }
1117
+
1118
+ static int SIGAPI ptql_args_match(sigar_t *sigar,
1119
+ sigar_pid_t pid,
1120
+ void *data)
1121
+ {
1122
+ ptql_branch_t *branch =
1123
+ (ptql_branch_t *)data;
1124
+ int status, matched=0;
1125
+ sigar_proc_args_t args;
1126
+
1127
+ status = sigar_proc_args_get(sigar, pid, &args);
1128
+ if (status != SIGAR_OK) {
1129
+ return status;
1130
+ }
1131
+
1132
+ if (branch->op_flags & PTQL_OP_FLAG_GLOB) {
1133
+ int i;
1134
+ for (i=0; i<args.number; i++) {
1135
+ matched =
1136
+ ptql_str_match(sigar, branch, args.data[i]);
1137
+
1138
+ if (matched) {
1139
+ break;
1140
+ }
1141
+ }
1142
+ }
1143
+ else {
1144
+ int num = branch->data.ui32;
1145
+
1146
+ /* e.g. find last element of args: Args.-1.eq=weblogic.Server */
1147
+ if (num < 0) {
1148
+ num += args.number;
1149
+ }
1150
+ if ((num >= 0) && (num < args.number)) {
1151
+ matched =
1152
+ ptql_str_match(sigar, branch, args.data[num]);
1153
+ }
1154
+ }
1155
+
1156
+ sigar_proc_args_destroy(sigar, &args);
1157
+
1158
+ return matched ? SIGAR_OK : !SIGAR_OK;
1159
+ }
1160
+
1161
+ typedef struct {
1162
+ sigar_t *sigar;
1163
+ ptql_branch_t *branch;
1164
+ sigar_uint32_t ix;
1165
+ int matched;
1166
+ } proc_modules_match_t;
1167
+
1168
+ static int proc_modules_match(void *data, char *name, int len)
1169
+ {
1170
+ proc_modules_match_t *matcher =
1171
+ (proc_modules_match_t *)data;
1172
+ ptql_branch_t *branch = matcher->branch;
1173
+
1174
+ if (branch->op_flags & PTQL_OP_FLAG_GLOB) { /* Modules.*.ct=libc */
1175
+ matcher->matched =
1176
+ ptql_str_match(matcher->sigar, branch, name);
1177
+
1178
+ if (matcher->matched) {
1179
+ return !SIGAR_OK; /* stop iterating */
1180
+ }
1181
+ }
1182
+ else {
1183
+ if (matcher->ix++ == branch->data.ui32) { /* Modules.3.ct=libc */
1184
+ matcher->matched =
1185
+ ptql_str_match(matcher->sigar, branch, name);
1186
+ return !SIGAR_OK; /* stop iterating */
1187
+ }
1188
+ }
1189
+
1190
+ return SIGAR_OK;
1191
+ }
1192
+
1193
+ static int SIGAPI ptql_modules_match(sigar_t *sigar,
1194
+ sigar_pid_t pid,
1195
+ void *data)
1196
+ {
1197
+ ptql_branch_t *branch =
1198
+ (ptql_branch_t *)data;
1199
+ int status;
1200
+ sigar_proc_modules_t procmods;
1201
+ proc_modules_match_t matcher;
1202
+
1203
+ matcher.sigar = sigar;
1204
+ matcher.branch = branch;
1205
+ matcher.ix = 0;
1206
+ matcher.matched = 0;
1207
+
1208
+ procmods.module_getter = proc_modules_match;
1209
+ procmods.data = &matcher;
1210
+
1211
+ status = sigar_proc_modules_get(sigar, pid, &procmods);
1212
+
1213
+ if (status != SIGAR_OK) {
1214
+ return status;
1215
+ }
1216
+
1217
+ return matcher.matched ? SIGAR_OK : !SIGAR_OK;
1218
+ }
1219
+
1220
+ typedef struct {
1221
+ const char *key;
1222
+ int klen;
1223
+ char *val;
1224
+ int vlen;
1225
+ } sigar_proc_env_entry_t;
1226
+
1227
+ static int sigar_proc_env_get_key(void *data,
1228
+ const char *key, int klen,
1229
+ char *val, int vlen)
1230
+ {
1231
+ sigar_proc_env_entry_t *entry =
1232
+ (sigar_proc_env_entry_t *)data;
1233
+
1234
+ if ((entry->klen == klen) &&
1235
+ (strcmp(entry->key, key) == 0))
1236
+ {
1237
+ entry->val = val;
1238
+ entry->vlen = vlen;
1239
+ return !SIGAR_OK; /* foundit; stop iterating */
1240
+ }
1241
+
1242
+ return SIGAR_OK;
1243
+ }
1244
+
1245
+ static int SIGAPI ptql_env_match(sigar_t *sigar,
1246
+ sigar_pid_t pid,
1247
+ void *data)
1248
+ {
1249
+ ptql_branch_t *branch =
1250
+ (ptql_branch_t *)data;
1251
+ int status, matched=0;
1252
+ sigar_proc_env_t procenv;
1253
+ sigar_proc_env_entry_t entry;
1254
+
1255
+ /* XXX ugh this is klunky */
1256
+ entry.key = branch->data.str;
1257
+ entry.klen = branch->data_size;
1258
+ entry.val = NULL;
1259
+
1260
+ procenv.type = SIGAR_PROC_ENV_KEY;
1261
+ procenv.key = branch->data.str;
1262
+ procenv.klen = branch->data_size;
1263
+ procenv.env_getter = sigar_proc_env_get_key;
1264
+ procenv.data = &entry;
1265
+
1266
+ status = sigar_proc_env_get(sigar, pid, &procenv);
1267
+ if (status != SIGAR_OK) {
1268
+ return status;
1269
+ }
1270
+ else {
1271
+ if (entry.val) {
1272
+ matched =
1273
+ ptql_str_match(sigar, branch, entry.val);
1274
+ }
1275
+ }
1276
+
1277
+ return matched ? SIGAR_OK : !SIGAR_OK;
1278
+ }
1279
+
1280
+ static int ptql_branch_init_port(ptql_parse_branch_t *parsed,
1281
+ ptql_branch_t *branch,
1282
+ sigar_ptql_error_t *error)
1283
+ {
1284
+ char *ptr;
1285
+
1286
+ /* only 'eq' is supported here */
1287
+ if (branch->op_name != PTQL_OP_EQ) {
1288
+ return ptql_error(error, "%s requires 'eq' operator",
1289
+ parsed->name);
1290
+ }
1291
+
1292
+ if (strEQ(parsed->attr, "tcp")) {
1293
+ branch->flags = PTQL_PID_TCP_PORT;
1294
+ }
1295
+ else if (strEQ(parsed->attr, "udp")) {
1296
+ branch->flags = PTQL_PID_TCP_PORT;
1297
+ }
1298
+ else {
1299
+ return ptql_error(error, "Unsupported %s protocol: %s",
1300
+ parsed->name, parsed->attr);
1301
+ }
1302
+
1303
+ branch->op_flags |= PTQL_OP_FLAG_PID;
1304
+ SIGAR_CLEAR_ERRNO();
1305
+ branch->data.ui32 = strtoul(parsed->value, &ptr, 10);
1306
+ if (strtonum_failed(parsed->value, ptr)) {
1307
+ return PTQL_ERRNAN;
1308
+ }
1309
+
1310
+ return SIGAR_OK;
1311
+ }
1312
+
1313
+ #define PTQL_LOOKUP_ENTRY(cname, member, type) \
1314
+ (ptql_get_t)sigar_##cname##_get, \
1315
+ sigar_offsetof(sigar_##cname##_t, member), \
1316
+ sizeof(sigar_##cname##_t), \
1317
+ PTQL_VALUE_TYPE_##type, \
1318
+ NULL
1319
+
1320
+ /* XXX uid/pid can be larger w/ 64bit mode */
1321
+ #define PTQL_VALUE_TYPE_PID PTQL_VALUE_TYPE_UI32
1322
+ #define PTQL_VALUE_TYPE_UID PTQL_VALUE_TYPE_UI32
1323
+
1324
+ static ptql_lookup_t PTQL_Time[] = {
1325
+ { "StartTime", PTQL_LOOKUP_ENTRY(proc_time, start_time, UI64) },
1326
+ { "User", PTQL_LOOKUP_ENTRY(proc_time, user, UI64) },
1327
+ { "Sys", PTQL_LOOKUP_ENTRY(proc_time, sys, UI64) },
1328
+ { "Total", PTQL_LOOKUP_ENTRY(proc_time, total, UI64) },
1329
+ { NULL }
1330
+ };
1331
+
1332
+ static ptql_lookup_t PTQL_Cpu[] = {
1333
+ { "StartTime", PTQL_LOOKUP_ENTRY(proc_cpu, start_time, UI64) },
1334
+ { "User", PTQL_LOOKUP_ENTRY(proc_cpu, user, UI64) },
1335
+ { "Sys", PTQL_LOOKUP_ENTRY(proc_cpu, sys, UI64) },
1336
+ { "Total", PTQL_LOOKUP_ENTRY(proc_cpu, total, UI64) },
1337
+ { "Percent", PTQL_LOOKUP_ENTRY(proc_cpu, percent, DBL) },
1338
+ { NULL }
1339
+ };
1340
+
1341
+ static ptql_lookup_t PTQL_Disk_IO[] = {
1342
+ { "BytesRead", PTQL_LOOKUP_ENTRY(proc_disk_io, bytes_read, UI64) },
1343
+ { "BytesWritten", PTQL_LOOKUP_ENTRY(proc_disk_io, bytes_written, UI64) },
1344
+ { "BytesTotal", PTQL_LOOKUP_ENTRY(proc_disk_io, bytes_total, UI64) },
1345
+ { NULL }
1346
+ };
1347
+
1348
+
1349
+ static ptql_lookup_t PTQL_CredName[] = {
1350
+ { "User", PTQL_LOOKUP_ENTRY(proc_cred_name, user, STR) },
1351
+ { "Group", PTQL_LOOKUP_ENTRY(proc_cred_name, group, STR) },
1352
+ { NULL }
1353
+ };
1354
+
1355
+ static ptql_lookup_t PTQL_Mem[] = {
1356
+ { "Size", PTQL_LOOKUP_ENTRY(proc_mem, size, UI64) },
1357
+ { "Resident", PTQL_LOOKUP_ENTRY(proc_mem, resident, UI64) },
1358
+ { "Share", PTQL_LOOKUP_ENTRY(proc_mem, share, UI64) },
1359
+ { "MinorFaults", PTQL_LOOKUP_ENTRY(proc_mem, minor_faults, UI64) },
1360
+ { "MajorFaults", PTQL_LOOKUP_ENTRY(proc_mem, major_faults, UI64) },
1361
+ { "PageFaults", PTQL_LOOKUP_ENTRY(proc_mem, page_faults, UI64) },
1362
+ { NULL }
1363
+ };
1364
+
1365
+ static ptql_lookup_t PTQL_Exe[] = {
1366
+ { "Name", PTQL_LOOKUP_ENTRY(proc_exe, name, STR) },
1367
+ { "Cwd", PTQL_LOOKUP_ENTRY(proc_exe, cwd, STR) },
1368
+ { NULL }
1369
+ };
1370
+
1371
+ static ptql_lookup_t PTQL_Cred[] = {
1372
+ { "Uid", PTQL_LOOKUP_ENTRY(proc_cred, uid, UID) },
1373
+ { "Gid", PTQL_LOOKUP_ENTRY(proc_cred, gid, UID) },
1374
+ { "Euid", PTQL_LOOKUP_ENTRY(proc_cred, euid, UID) },
1375
+ { "Egid", PTQL_LOOKUP_ENTRY(proc_cred, egid, UID) },
1376
+ { NULL }
1377
+ };
1378
+
1379
+ static ptql_lookup_t PTQL_State[] = {
1380
+ { "State", PTQL_LOOKUP_ENTRY(proc_state, state, CHR) },
1381
+ { "Name", PTQL_LOOKUP_ENTRY(proc_state, name, STR) },
1382
+ { "Ppid", PTQL_LOOKUP_ENTRY(proc_state, ppid, PID) },
1383
+ { "Tty", PTQL_LOOKUP_ENTRY(proc_state, tty, UI32) },
1384
+ { "Nice", PTQL_LOOKUP_ENTRY(proc_state, nice, UI32) },
1385
+ { "Priority", PTQL_LOOKUP_ENTRY(proc_state, priority, UI32) },
1386
+ { "Threads", PTQL_LOOKUP_ENTRY(proc_state, threads, UI64) },
1387
+ { "Processor", PTQL_LOOKUP_ENTRY(proc_state, processor, UI32) },
1388
+ { NULL }
1389
+ };
1390
+
1391
+ static ptql_lookup_t PTQL_Fd[] = {
1392
+ { "Total", PTQL_LOOKUP_ENTRY(proc_fd, total, UI64) },
1393
+ { NULL }
1394
+ };
1395
+
1396
+ static ptql_lookup_t PTQL_Args[] = {
1397
+ { NULL, ptql_args_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_args_branch_init }
1398
+ };
1399
+
1400
+ static ptql_lookup_t PTQL_Modules[] = {
1401
+ { NULL, ptql_modules_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_args_branch_init }
1402
+ };
1403
+
1404
+ static ptql_lookup_t PTQL_Env[] = {
1405
+ { NULL, ptql_env_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_any }
1406
+ };
1407
+
1408
+ static ptql_lookup_t PTQL_Port[] = {
1409
+ { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_port }
1410
+ };
1411
+
1412
+ static ptql_lookup_t PTQL_Pid[] = {
1413
+ { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_pid }
1414
+ };
1415
+
1416
+ static ptql_lookup_t PTQL_Service[] = {
1417
+ { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_service }
1418
+ };
1419
+
1420
+ static ptql_entry_t ptql_map[] = {
1421
+ { "Time", PTQL_Time },
1422
+ { "Cpu", PTQL_Cpu },
1423
+ { "CredName", PTQL_CredName },
1424
+ { "Mem", PTQL_Mem },
1425
+ { "Exe", PTQL_Exe },
1426
+ { "Cred", PTQL_Cred },
1427
+ { "State", PTQL_State },
1428
+ { "Fd", PTQL_Fd },
1429
+ { "Args", PTQL_Args },
1430
+ { "Modules", PTQL_Modules },
1431
+ { "Env", PTQL_Env },
1432
+ { "Port", PTQL_Port },
1433
+ { "Pid", PTQL_Pid },
1434
+ { "Service", PTQL_Service },
1435
+ { "Disk_IO", PTQL_Disk_IO },
1436
+ { NULL }
1437
+ };
1438
+
1439
+ static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch,
1440
+ sigar_ptql_error_t *error)
1441
+ {
1442
+ char *ptr = strchr(query, '=');
1443
+ if (!ptr) {
1444
+ return ptql_error(error, "Missing '='");
1445
+ }
1446
+
1447
+ branch->op_flags = 0;
1448
+
1449
+ *ptr = '\0';
1450
+ branch->value = ++ptr;
1451
+
1452
+ if ((ptr = strchr(query, '.'))) {
1453
+ *ptr = '\0';
1454
+ branch->name = query;
1455
+ query = ++ptr;
1456
+ }
1457
+ else {
1458
+ return ptql_error(error, "Missing '.'");
1459
+ }
1460
+
1461
+ if ((ptr = strchr(query, '.'))) {
1462
+ *ptr = '\0';
1463
+ branch->attr = query;
1464
+ query = ++ptr;
1465
+ }
1466
+ else {
1467
+ return ptql_error(error, "Missing '.'");
1468
+ }
1469
+
1470
+ if (*query) {
1471
+ char flag;
1472
+
1473
+ while (sigar_isupper((flag = *query))) {
1474
+ switch (flag) {
1475
+ case 'P':
1476
+ branch->op_flags |= PTQL_OP_FLAG_PARENT;
1477
+ break;
1478
+ case 'I':
1479
+ branch->op_flags |= PTQL_OP_FLAG_ICASE;
1480
+ break;
1481
+ default:
1482
+ return ptql_error(error, "Unsupported modifier: %c", flag);
1483
+ }
1484
+
1485
+ ++query;
1486
+ }
1487
+
1488
+ branch->op = query;
1489
+ }
1490
+ else {
1491
+ return ptql_error(error, "Missing query");
1492
+ }
1493
+
1494
+ /* Pid.Service -> Service.Name */
1495
+ if (strEQ(branch->attr, "Service")) {
1496
+ branch->name = branch->attr;
1497
+ branch->attr = "Name";
1498
+ }
1499
+
1500
+ return SIGAR_OK;
1501
+ }
1502
+
1503
+ static int ptql_branch_add(ptql_parse_branch_t *parsed,
1504
+ ptql_branch_list_t *branches,
1505
+ sigar_ptql_error_t *error)
1506
+ {
1507
+ ptql_branch_t *branch;
1508
+ ptql_entry_t *entry = NULL;
1509
+ ptql_lookup_t *lookup = NULL;
1510
+ int i, is_set=0;
1511
+ char *ptr;
1512
+
1513
+ PTQL_BRANCH_LIST_GROW(branches);
1514
+
1515
+ branch = &branches->data[branches->number++];
1516
+ SIGAR_ZERO(branch);
1517
+ branch->data_free = data_free;
1518
+ branch->value_free = data_free;
1519
+ branch->op_flags = parsed->op_flags;
1520
+
1521
+ branch->op_name = ptql_op_code_get(parsed->op);
1522
+ if (branch->op_name == PTQL_OP_MAX) {
1523
+ return ptql_error(error, "Unsupported operator: %s", parsed->op);
1524
+ }
1525
+
1526
+ for (i=0; ptql_map[i].name; i++) {
1527
+ if (strEQ(ptql_map[i].name, parsed->name)) {
1528
+ entry = &ptql_map[i];
1529
+ break;
1530
+ }
1531
+ }
1532
+
1533
+ if (!entry) {
1534
+ return ptql_error(error, "Unsupported method: %s", parsed->name);
1535
+ }
1536
+
1537
+ for (i=0; entry->members[i].name; i++) {
1538
+ if (strEQ(entry->members[i].name, parsed->attr)) {
1539
+ lookup = &entry->members[i];
1540
+ break;
1541
+ }
1542
+ }
1543
+
1544
+ if (!lookup) {
1545
+ if (entry->members[0].type == PTQL_VALUE_TYPE_ANY) {
1546
+ /* Args, Env, etc. */
1547
+ lookup = &entry->members[0];
1548
+ }
1549
+ else {
1550
+ return ptql_error(error, "Unsupported %s attribute: %s",
1551
+ parsed->name, parsed->attr);
1552
+ }
1553
+ }
1554
+
1555
+ if (lookup->init) {
1556
+ int status = lookup->init(parsed, branch, error);
1557
+ if (status != SIGAR_OK) {
1558
+ return status;
1559
+ }
1560
+ }
1561
+
1562
+ branch->lookup = lookup;
1563
+
1564
+ if ((lookup->type < PTQL_VALUE_TYPE_STR) &&
1565
+ (branch->op_name > PTQL_OP_MAX_NSTR))
1566
+ {
1567
+ return ptql_error(error, "Unsupported operator '%s' for %s.%s",
1568
+ parsed->op, parsed->name, parsed->attr);
1569
+ }
1570
+
1571
+ if (*parsed->value == '$') {
1572
+ is_set = 1;
1573
+
1574
+ if (branch->op_name == PTQL_OP_RE) {
1575
+ /* not for use with .re */
1576
+ return ptql_error(error, "Unsupported operator '%s' with variable %s",
1577
+ parsed->op, parsed->value);
1578
+ }
1579
+
1580
+ if (sigar_isdigit(*(parsed->value+1))) {
1581
+ branch->op_flags |= PTQL_OP_FLAG_REF;
1582
+ parsed->op_flags = branch->op_flags; /* for use by caller */
1583
+ branch->value.ui32 = atoi(parsed->value+1) - 1;
1584
+
1585
+ if (branch->value.ui32 >= branches->number) {
1586
+ /* out-of-range */
1587
+ return ptql_error(error, "Variable %s out of range (%d)",
1588
+ parsed->value, branches->number);
1589
+ }
1590
+ else if (branch->value.ui32 == branches->number-1) {
1591
+ /* self reference */
1592
+ return ptql_error(error, "Variable %s self reference",
1593
+ parsed->value);
1594
+ }
1595
+ }
1596
+ else {
1597
+ if ((ptr = getenv(parsed->value+1))) {
1598
+ branch->value.str = sigar_strdup(ptr);
1599
+ }
1600
+ else {
1601
+ branch->value.str = NULL;
1602
+ }
1603
+ }
1604
+ }
1605
+ else if (branch->op_name == PTQL_OP_RE) {
1606
+ #ifdef SIGAR_HAS_PCRE
1607
+ const char *error;
1608
+ int offset;
1609
+ pcre *re =
1610
+ pcre_compile(parsed->value, 0,
1611
+ &error, &offset, NULL);
1612
+ if (!re) {
1613
+ /* XXX pcre_error ? */
1614
+ return ptql_error(error, "Invalid regex");
1615
+ }
1616
+ is_set = 1;
1617
+ branch->value.ptr = re;
1618
+ branch->value_free = pcre_free;
1619
+ #endif
1620
+ }
1621
+
1622
+ switch (lookup->type) {
1623
+ case PTQL_VALUE_TYPE_UI64:
1624
+ branch->match.ui64 = ptql_op_ui64[branch->op_name];
1625
+ if (!is_set) {
1626
+ SIGAR_CLEAR_ERRNO();
1627
+ branch->value.ui64 = strtoull(parsed->value, &ptr, 10);
1628
+ if (strtonum_failed(parsed->value, ptr)) {
1629
+ return PTQL_ERRNAN;
1630
+ }
1631
+ }
1632
+ break;
1633
+ case PTQL_VALUE_TYPE_UI32:
1634
+ branch->match.ui32 = ptql_op_ui32[branch->op_name];
1635
+ if (!is_set) {
1636
+ SIGAR_CLEAR_ERRNO();
1637
+ branch->value.ui32 = strtoul(parsed->value, &ptr, 10);
1638
+ if (strtonum_failed(parsed->value, ptr)) {
1639
+ return PTQL_ERRNAN;
1640
+ }
1641
+ }
1642
+ break;
1643
+ case PTQL_VALUE_TYPE_DBL:
1644
+ branch->match.dbl = ptql_op_dbl[branch->op_name];
1645
+ if (!is_set) {
1646
+ SIGAR_CLEAR_ERRNO();
1647
+ branch->value.dbl = strtod(parsed->value, &ptr);
1648
+ if (strtonum_failed(parsed->value, ptr)) {
1649
+ return PTQL_ERRNAN;
1650
+ }
1651
+ }
1652
+ break;
1653
+ case PTQL_VALUE_TYPE_CHR:
1654
+ branch->match.chr = ptql_op_chr[branch->op_name];
1655
+ if (!is_set) {
1656
+ if (strlen(parsed->value) != 1) {
1657
+ return ptql_error(error, "%s is not a char", parsed->value);
1658
+ }
1659
+ branch->value.chr[0] = parsed->value[0];
1660
+ }
1661
+ break;
1662
+ case PTQL_VALUE_TYPE_STR:
1663
+ case PTQL_VALUE_TYPE_ANY:
1664
+ branch->match.str = ptql_op_str[branch->op_name];
1665
+ if (!is_set) {
1666
+ branch->value.str = sigar_strdup(parsed->value);
1667
+ }
1668
+ break;
1669
+ }
1670
+
1671
+ return SIGAR_OK;
1672
+ }
1673
+
1674
+ static int ptql_branch_compare(const void *b1, const void *b2)
1675
+ {
1676
+ /* XXX can do better */
1677
+ ptql_branch_t *branch1 = (ptql_branch_t *)b1;
1678
+ ptql_branch_t *branch2 = (ptql_branch_t *)b2;
1679
+ return
1680
+ branch1->lookup->type -
1681
+ branch2->lookup->type;
1682
+ }
1683
+
1684
+ SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp,
1685
+ char *ptql,
1686
+ sigar_ptql_error_t *error)
1687
+ {
1688
+ char *ptr, *ptql_copy = sigar_strdup(ptql);
1689
+ int status = SIGAR_OK;
1690
+ int has_ref = 0;
1691
+ sigar_ptql_query_t *query =
1692
+ *queryp = malloc(sizeof(*query));
1693
+
1694
+ (void)ptql_error(error, "Malformed query");
1695
+
1696
+ #ifdef PTQL_DEBUG
1697
+ query->ptql = sigar_strdup(ptql);
1698
+ #endif
1699
+
1700
+ ptql = ptql_copy;
1701
+
1702
+ ptql_branch_list_create(&query->branches);
1703
+
1704
+ do {
1705
+ ptql_parse_branch_t parsed;
1706
+
1707
+ if ((ptr = strchr(ptql, ','))) {
1708
+ *ptr = '\0';
1709
+ }
1710
+
1711
+ status = ptql_branch_parse(ptql, &parsed, error);
1712
+ if (status == SIGAR_OK) {
1713
+ status =
1714
+ ptql_branch_add(&parsed, &query->branches, error);
1715
+
1716
+ if (status != SIGAR_OK) {
1717
+ break;
1718
+ }
1719
+ if (parsed.op_flags & PTQL_OP_FLAG_REF) {
1720
+ has_ref = 1;
1721
+ }
1722
+ }
1723
+ else {
1724
+ break;
1725
+ }
1726
+
1727
+ if (ptr) {
1728
+ ptql = ++ptr;
1729
+ }
1730
+ else {
1731
+ break;
1732
+ }
1733
+ } while (*ptql);
1734
+
1735
+ free(ptql_copy);
1736
+
1737
+ if (status != SIGAR_OK) {
1738
+ sigar_ptql_query_destroy(query);
1739
+ *queryp = NULL;
1740
+ }
1741
+ else if (!has_ref && (query->branches.number > 1)) {
1742
+ qsort(query->branches.data,
1743
+ query->branches.number,
1744
+ sizeof(query->branches.data[0]),
1745
+ ptql_branch_compare);
1746
+ }
1747
+
1748
+ if (status == SIGAR_OK) {
1749
+ (void)ptql_error(error, "OK");
1750
+ }
1751
+ return status;
1752
+ }
1753
+
1754
+ SIGAR_DECLARE(int) sigar_ptql_query_destroy(sigar_ptql_query_t *query)
1755
+ {
1756
+ #ifdef PTQL_DEBUG
1757
+ free(query->ptql);
1758
+ #endif
1759
+ ptql_branch_list_destroy(&query->branches);
1760
+ free(query);
1761
+ return SIGAR_OK;
1762
+ }
1763
+
1764
+ SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data,
1765
+ sigar_ptql_re_impl_t impl)
1766
+ {
1767
+ sigar->ptql_re_data = data;
1768
+ sigar->ptql_re_impl = impl;
1769
+ }
1770
+
1771
+ SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar,
1772
+ sigar_ptql_query_t *query,
1773
+ sigar_pid_t query_pid)
1774
+ {
1775
+ int i;
1776
+
1777
+ for (i=0; i<query->branches.number; i++) {
1778
+ sigar_pid_t pid = query_pid;
1779
+ int status, matched=0;
1780
+ ptql_branch_t *branch = &query->branches.data[i];
1781
+ ptql_lookup_t *lookup = branch->lookup;
1782
+
1783
+ if (branch->op_flags & PTQL_OP_FLAG_PARENT) {
1784
+ sigar_proc_state_t state;
1785
+
1786
+ status = sigar_proc_state_get(sigar, pid, &state);
1787
+ if (status != SIGAR_OK) {
1788
+ return status;
1789
+ }
1790
+
1791
+ pid = state.ppid;
1792
+ }
1793
+
1794
+ if (lookup->type == PTQL_VALUE_TYPE_ANY) {
1795
+ /* Args, Env, etc. */
1796
+ status = lookup->get(sigar, pid, branch);
1797
+ if (status == SIGAR_OK) {
1798
+ matched = 1;
1799
+ }
1800
+ }
1801
+ else {
1802
+ /* standard sigar_proc_*_get / structptr + offset */
1803
+ if (!branch->data.ptr) {
1804
+ branch->data_size = lookup->data_size;
1805
+ branch->data.ptr = malloc(branch->data_size);
1806
+ }
1807
+ status = lookup->get(sigar, pid, branch->data.ptr);
1808
+ if (status != SIGAR_OK) {
1809
+ return status;
1810
+ }
1811
+
1812
+ if (branch->op_flags & PTQL_OP_FLAG_REF) {
1813
+ ptql_branch_t *ref =
1814
+ &query->branches.data[branch->value.ui32];
1815
+
1816
+ matched = ptql_branch_match_ref(branch, ref);
1817
+ }
1818
+ #ifndef SIGAR_HAS_PCRE
1819
+ else if (branch->lookup->type == PTQL_VALUE_TYPE_STR) {
1820
+ matched = ptql_str_match(sigar, branch, (char *)DATA_PTR(branch));
1821
+ }
1822
+ #endif
1823
+ else {
1824
+ matched = ptql_branch_match(branch);
1825
+ }
1826
+ }
1827
+
1828
+ if (!matched) {
1829
+ return 1;
1830
+ }
1831
+ }
1832
+
1833
+ return SIGAR_OK;
1834
+ }
1835
+
1836
+ static int ptql_proc_list_get(sigar_t *sigar,
1837
+ sigar_ptql_query_t *query,
1838
+ sigar_proc_list_t **proclist)
1839
+ {
1840
+ int status;
1841
+ int i;
1842
+
1843
+ *proclist = NULL;
1844
+
1845
+ for (i=0; i<query->branches.number; i++) {
1846
+ ptql_branch_t *branch = &query->branches.data[i];
1847
+
1848
+ if (branch->op_flags & PTQL_OP_FLAG_PID) {
1849
+ /* pre-filter pid list for Pid.* queries */
1850
+ /* XXX multiple Pid.* may result in dups */
1851
+ if (*proclist == NULL) {
1852
+ *proclist = malloc(sizeof(**proclist));
1853
+ SIGAR_ZERO(*proclist);
1854
+ sigar_proc_list_create(*proclist);
1855
+ }
1856
+ status = ptql_pid_list_get(sigar, branch, *proclist);
1857
+ if (status != SIGAR_OK) {
1858
+ sigar_proc_list_destroy(sigar, *proclist);
1859
+ free(*proclist);
1860
+ return status;
1861
+ }
1862
+ }
1863
+ }
1864
+
1865
+ if (*proclist) {
1866
+ return SIGAR_OK;
1867
+ }
1868
+
1869
+ status = sigar_proc_list_get(sigar, NULL);
1870
+ if (status != SIGAR_OK) {
1871
+ return status;
1872
+ }
1873
+ *proclist = sigar->pids;
1874
+ return SIGAR_OK;
1875
+ }
1876
+
1877
+ static int ptql_proc_list_destroy(sigar_t *sigar,
1878
+ sigar_proc_list_t *proclist)
1879
+ {
1880
+ if (proclist != sigar->pids) {
1881
+ sigar_proc_list_destroy(sigar, proclist);
1882
+ free(proclist);
1883
+ }
1884
+
1885
+ return SIGAR_OK;
1886
+ }
1887
+
1888
+ SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar,
1889
+ sigar_ptql_query_t *query,
1890
+ sigar_pid_t *pid)
1891
+ {
1892
+ int status;
1893
+ int i, matches=0;
1894
+ sigar_proc_list_t *pids;
1895
+
1896
+ status = ptql_proc_list_get(sigar, query, &pids);
1897
+ if (status != SIGAR_OK) {
1898
+ return status;
1899
+ }
1900
+
1901
+ for (i=0; i<pids->number; i++) {
1902
+ int query_status =
1903
+ sigar_ptql_query_match(sigar, query, pids->data[i]);
1904
+
1905
+ if (query_status == SIGAR_OK) {
1906
+ *pid = pids->data[i];
1907
+ matches++;
1908
+ }
1909
+ else if (query_status == SIGAR_ENOTIMPL) {
1910
+ /* let caller know query is invalid. */
1911
+ status = query_status;
1912
+ break;
1913
+ } /* else ok, e.g. permission denied */
1914
+ }
1915
+
1916
+ ptql_proc_list_destroy(sigar, pids);
1917
+
1918
+ if (status != SIGAR_OK) {
1919
+ return status;
1920
+ }
1921
+
1922
+ if (matches == 1) {
1923
+ return SIGAR_OK;
1924
+ }
1925
+ else if (matches == 0) {
1926
+ sigar_strerror_set(sigar,
1927
+ "Query did not match any processes");
1928
+ }
1929
+ else {
1930
+ sigar_strerror_printf(sigar,
1931
+ "Query matched multiple processes (%d)",
1932
+ matches);
1933
+ }
1934
+
1935
+ return -1;
1936
+ }
1937
+
1938
+ SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar,
1939
+ sigar_ptql_query_t *query,
1940
+ sigar_proc_list_t *proclist)
1941
+ {
1942
+ int status;
1943
+ int i;
1944
+ sigar_proc_list_t *pids;
1945
+
1946
+ status = ptql_proc_list_get(sigar, query, &pids);
1947
+ if (status != SIGAR_OK) {
1948
+ return status;
1949
+ }
1950
+
1951
+ sigar_proc_list_create(proclist);
1952
+
1953
+ for (i=0; i<pids->number; i++) {
1954
+ int query_status =
1955
+ sigar_ptql_query_match(sigar, query, pids->data[i]);
1956
+
1957
+ if (query_status == SIGAR_OK) {
1958
+ SIGAR_PROC_LIST_GROW(proclist);
1959
+ proclist->data[proclist->number++] = pids->data[i];
1960
+ }
1961
+ else if (query_status == SIGAR_ENOTIMPL) {
1962
+ /* let caller know query is invalid. */
1963
+ status = query_status;
1964
+ break;
1965
+ }
1966
+ }
1967
+
1968
+ ptql_proc_list_destroy(sigar, pids);
1969
+
1970
+ if (status != SIGAR_OK) {
1971
+ sigar_proc_list_destroy(sigar, proclist);
1972
+ return status;
1973
+ }
1974
+
1975
+ return SIGAR_OK;
1976
+ }