sigar 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1967 +0,0 @@
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_CredName[] = {
1342
- { "User", PTQL_LOOKUP_ENTRY(proc_cred_name, user, STR) },
1343
- { "Group", PTQL_LOOKUP_ENTRY(proc_cred_name, group, STR) },
1344
- { NULL }
1345
- };
1346
-
1347
- static ptql_lookup_t PTQL_Mem[] = {
1348
- { "Size", PTQL_LOOKUP_ENTRY(proc_mem, size, UI64) },
1349
- { "Resident", PTQL_LOOKUP_ENTRY(proc_mem, resident, UI64) },
1350
- { "Share", PTQL_LOOKUP_ENTRY(proc_mem, share, UI64) },
1351
- { "MinorFaults", PTQL_LOOKUP_ENTRY(proc_mem, minor_faults, UI64) },
1352
- { "MajorFaults", PTQL_LOOKUP_ENTRY(proc_mem, major_faults, UI64) },
1353
- { "PageFaults", PTQL_LOOKUP_ENTRY(proc_mem, page_faults, UI64) },
1354
- { NULL }
1355
- };
1356
-
1357
- static ptql_lookup_t PTQL_Exe[] = {
1358
- { "Name", PTQL_LOOKUP_ENTRY(proc_exe, name, STR) },
1359
- { "Cwd", PTQL_LOOKUP_ENTRY(proc_exe, cwd, STR) },
1360
- { NULL }
1361
- };
1362
-
1363
- static ptql_lookup_t PTQL_Cred[] = {
1364
- { "Uid", PTQL_LOOKUP_ENTRY(proc_cred, uid, UID) },
1365
- { "Gid", PTQL_LOOKUP_ENTRY(proc_cred, gid, UID) },
1366
- { "Euid", PTQL_LOOKUP_ENTRY(proc_cred, euid, UID) },
1367
- { "Egid", PTQL_LOOKUP_ENTRY(proc_cred, egid, UID) },
1368
- { NULL }
1369
- };
1370
-
1371
- static ptql_lookup_t PTQL_State[] = {
1372
- { "State", PTQL_LOOKUP_ENTRY(proc_state, state, CHR) },
1373
- { "Name", PTQL_LOOKUP_ENTRY(proc_state, name, STR) },
1374
- { "Ppid", PTQL_LOOKUP_ENTRY(proc_state, ppid, PID) },
1375
- { "Tty", PTQL_LOOKUP_ENTRY(proc_state, tty, UI32) },
1376
- { "Nice", PTQL_LOOKUP_ENTRY(proc_state, nice, UI32) },
1377
- { "Priority", PTQL_LOOKUP_ENTRY(proc_state, priority, UI32) },
1378
- { "Threads", PTQL_LOOKUP_ENTRY(proc_state, threads, UI64) },
1379
- { "Processor", PTQL_LOOKUP_ENTRY(proc_state, processor, UI32) },
1380
- { NULL }
1381
- };
1382
-
1383
- static ptql_lookup_t PTQL_Fd[] = {
1384
- { "Total", PTQL_LOOKUP_ENTRY(proc_fd, total, UI64) },
1385
- { NULL }
1386
- };
1387
-
1388
- static ptql_lookup_t PTQL_Args[] = {
1389
- { NULL, ptql_args_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_args_branch_init }
1390
- };
1391
-
1392
- static ptql_lookup_t PTQL_Modules[] = {
1393
- { NULL, ptql_modules_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_args_branch_init }
1394
- };
1395
-
1396
- static ptql_lookup_t PTQL_Env[] = {
1397
- { NULL, ptql_env_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_any }
1398
- };
1399
-
1400
- static ptql_lookup_t PTQL_Port[] = {
1401
- { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_port }
1402
- };
1403
-
1404
- static ptql_lookup_t PTQL_Pid[] = {
1405
- { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_pid }
1406
- };
1407
-
1408
- static ptql_lookup_t PTQL_Service[] = {
1409
- { NULL, ptql_pid_match, 0, 0, PTQL_VALUE_TYPE_ANY, ptql_branch_init_service }
1410
- };
1411
-
1412
- static ptql_entry_t ptql_map[] = {
1413
- { "Time", PTQL_Time },
1414
- { "Cpu", PTQL_Cpu },
1415
- { "CredName", PTQL_CredName },
1416
- { "Mem", PTQL_Mem },
1417
- { "Exe", PTQL_Exe },
1418
- { "Cred", PTQL_Cred },
1419
- { "State", PTQL_State },
1420
- { "Fd", PTQL_Fd },
1421
- { "Args", PTQL_Args },
1422
- { "Modules", PTQL_Modules },
1423
- { "Env", PTQL_Env },
1424
- { "Port", PTQL_Port },
1425
- { "Pid", PTQL_Pid },
1426
- { "Service", PTQL_Service },
1427
- { NULL }
1428
- };
1429
-
1430
- static int ptql_branch_parse(char *query, ptql_parse_branch_t *branch,
1431
- sigar_ptql_error_t *error)
1432
- {
1433
- char *ptr = strchr(query, '=');
1434
- if (!ptr) {
1435
- return ptql_error(error, "Missing '='");
1436
- }
1437
-
1438
- branch->op_flags = 0;
1439
-
1440
- *ptr = '\0';
1441
- branch->value = ++ptr;
1442
-
1443
- if ((ptr = strchr(query, '.'))) {
1444
- *ptr = '\0';
1445
- branch->name = query;
1446
- query = ++ptr;
1447
- }
1448
- else {
1449
- return ptql_error(error, "Missing '.'");
1450
- }
1451
-
1452
- if ((ptr = strchr(query, '.'))) {
1453
- *ptr = '\0';
1454
- branch->attr = query;
1455
- query = ++ptr;
1456
- }
1457
- else {
1458
- return ptql_error(error, "Missing '.'");
1459
- }
1460
-
1461
- if (*query) {
1462
- char flag;
1463
-
1464
- while (sigar_isupper((flag = *query))) {
1465
- switch (flag) {
1466
- case 'P':
1467
- branch->op_flags |= PTQL_OP_FLAG_PARENT;
1468
- break;
1469
- case 'I':
1470
- branch->op_flags |= PTQL_OP_FLAG_ICASE;
1471
- break;
1472
- default:
1473
- return ptql_error(error, "Unsupported modifier: %c", flag);
1474
- }
1475
-
1476
- ++query;
1477
- }
1478
-
1479
- branch->op = query;
1480
- }
1481
- else {
1482
- return ptql_error(error, "Missing query");
1483
- }
1484
-
1485
- /* Pid.Service -> Service.Name */
1486
- if (strEQ(branch->attr, "Service")) {
1487
- branch->name = branch->attr;
1488
- branch->attr = "Name";
1489
- }
1490
-
1491
- return SIGAR_OK;
1492
- }
1493
-
1494
- static int ptql_branch_add(ptql_parse_branch_t *parsed,
1495
- ptql_branch_list_t *branches,
1496
- sigar_ptql_error_t *error)
1497
- {
1498
- ptql_branch_t *branch;
1499
- ptql_entry_t *entry = NULL;
1500
- ptql_lookup_t *lookup = NULL;
1501
- int i, is_set=0;
1502
- char *ptr;
1503
-
1504
- PTQL_BRANCH_LIST_GROW(branches);
1505
-
1506
- branch = &branches->data[branches->number++];
1507
- SIGAR_ZERO(branch);
1508
- branch->data_free = data_free;
1509
- branch->value_free = data_free;
1510
- branch->op_flags = parsed->op_flags;
1511
-
1512
- branch->op_name = ptql_op_code_get(parsed->op);
1513
- if (branch->op_name == PTQL_OP_MAX) {
1514
- return ptql_error(error, "Unsupported operator: %s", parsed->op);
1515
- }
1516
-
1517
- for (i=0; ptql_map[i].name; i++) {
1518
- if (strEQ(ptql_map[i].name, parsed->name)) {
1519
- entry = &ptql_map[i];
1520
- break;
1521
- }
1522
- }
1523
-
1524
- if (!entry) {
1525
- return ptql_error(error, "Unsupported method: %s", parsed->name);
1526
- }
1527
-
1528
- for (i=0; entry->members[i].name; i++) {
1529
- if (strEQ(entry->members[i].name, parsed->attr)) {
1530
- lookup = &entry->members[i];
1531
- break;
1532
- }
1533
- }
1534
-
1535
- if (!lookup) {
1536
- if (entry->members[0].type == PTQL_VALUE_TYPE_ANY) {
1537
- /* Args, Env, etc. */
1538
- lookup = &entry->members[0];
1539
- }
1540
- else {
1541
- return ptql_error(error, "Unsupported %s attribute: %s",
1542
- parsed->name, parsed->attr);
1543
- }
1544
- }
1545
-
1546
- if (lookup->init) {
1547
- int status = lookup->init(parsed, branch, error);
1548
- if (status != SIGAR_OK) {
1549
- return status;
1550
- }
1551
- }
1552
-
1553
- branch->lookup = lookup;
1554
-
1555
- if ((lookup->type < PTQL_VALUE_TYPE_STR) &&
1556
- (branch->op_name > PTQL_OP_MAX_NSTR))
1557
- {
1558
- return ptql_error(error, "Unsupported operator '%s' for %s.%s",
1559
- parsed->op, parsed->name, parsed->attr);
1560
- }
1561
-
1562
- if (*parsed->value == '$') {
1563
- is_set = 1;
1564
-
1565
- if (branch->op_name == PTQL_OP_RE) {
1566
- /* not for use with .re */
1567
- return ptql_error(error, "Unsupported operator '%s' with variable %s",
1568
- parsed->op, parsed->value);
1569
- }
1570
-
1571
- if (sigar_isdigit(*(parsed->value+1))) {
1572
- branch->op_flags |= PTQL_OP_FLAG_REF;
1573
- parsed->op_flags = branch->op_flags; /* for use by caller */
1574
- branch->value.ui32 = atoi(parsed->value+1) - 1;
1575
-
1576
- if (branch->value.ui32 >= branches->number) {
1577
- /* out-of-range */
1578
- return ptql_error(error, "Variable %s out of range (%d)",
1579
- parsed->value, branches->number);
1580
- }
1581
- else if (branch->value.ui32 == branches->number-1) {
1582
- /* self reference */
1583
- return ptql_error(error, "Variable %s self reference",
1584
- parsed->value);
1585
- }
1586
- }
1587
- else {
1588
- if ((ptr = getenv(parsed->value+1))) {
1589
- branch->value.str = sigar_strdup(ptr);
1590
- }
1591
- else {
1592
- branch->value.str = NULL;
1593
- }
1594
- }
1595
- }
1596
- else if (branch->op_name == PTQL_OP_RE) {
1597
- #ifdef SIGAR_HAS_PCRE
1598
- const char *error;
1599
- int offset;
1600
- pcre *re =
1601
- pcre_compile(parsed->value, 0,
1602
- &error, &offset, NULL);
1603
- if (!re) {
1604
- /* XXX pcre_error ? */
1605
- return ptql_error(error, "Invalid regex");
1606
- }
1607
- is_set = 1;
1608
- branch->value.ptr = re;
1609
- branch->value_free = pcre_free;
1610
- #endif
1611
- }
1612
-
1613
- switch (lookup->type) {
1614
- case PTQL_VALUE_TYPE_UI64:
1615
- branch->match.ui64 = ptql_op_ui64[branch->op_name];
1616
- if (!is_set) {
1617
- SIGAR_CLEAR_ERRNO();
1618
- branch->value.ui64 = strtoull(parsed->value, &ptr, 10);
1619
- if (strtonum_failed(parsed->value, ptr)) {
1620
- return PTQL_ERRNAN;
1621
- }
1622
- }
1623
- break;
1624
- case PTQL_VALUE_TYPE_UI32:
1625
- branch->match.ui32 = ptql_op_ui32[branch->op_name];
1626
- if (!is_set) {
1627
- SIGAR_CLEAR_ERRNO();
1628
- branch->value.ui32 = strtoul(parsed->value, &ptr, 10);
1629
- if (strtonum_failed(parsed->value, ptr)) {
1630
- return PTQL_ERRNAN;
1631
- }
1632
- }
1633
- break;
1634
- case PTQL_VALUE_TYPE_DBL:
1635
- branch->match.dbl = ptql_op_dbl[branch->op_name];
1636
- if (!is_set) {
1637
- SIGAR_CLEAR_ERRNO();
1638
- branch->value.dbl = strtod(parsed->value, &ptr);
1639
- if (strtonum_failed(parsed->value, ptr)) {
1640
- return PTQL_ERRNAN;
1641
- }
1642
- }
1643
- break;
1644
- case PTQL_VALUE_TYPE_CHR:
1645
- branch->match.chr = ptql_op_chr[branch->op_name];
1646
- if (!is_set) {
1647
- if (strlen(parsed->value) != 1) {
1648
- return ptql_error(error, "%s is not a char", parsed->value);
1649
- }
1650
- branch->value.chr[0] = parsed->value[0];
1651
- }
1652
- break;
1653
- case PTQL_VALUE_TYPE_STR:
1654
- case PTQL_VALUE_TYPE_ANY:
1655
- branch->match.str = ptql_op_str[branch->op_name];
1656
- if (!is_set) {
1657
- branch->value.str = sigar_strdup(parsed->value);
1658
- }
1659
- break;
1660
- }
1661
-
1662
- return SIGAR_OK;
1663
- }
1664
-
1665
- static int ptql_branch_compare(const void *b1, const void *b2)
1666
- {
1667
- /* XXX can do better */
1668
- ptql_branch_t *branch1 = (ptql_branch_t *)b1;
1669
- ptql_branch_t *branch2 = (ptql_branch_t *)b2;
1670
- return
1671
- branch1->lookup->type -
1672
- branch2->lookup->type;
1673
- }
1674
-
1675
- SIGAR_DECLARE(int) sigar_ptql_query_create(sigar_ptql_query_t **queryp,
1676
- char *ptql,
1677
- sigar_ptql_error_t *error)
1678
- {
1679
- char *ptr, *ptql_copy = sigar_strdup(ptql);
1680
- int status = SIGAR_OK;
1681
- int has_ref = 0;
1682
- sigar_ptql_query_t *query =
1683
- *queryp = malloc(sizeof(*query));
1684
-
1685
- (void)ptql_error(error, "Malformed query");
1686
-
1687
- #ifdef PTQL_DEBUG
1688
- query->ptql = sigar_strdup(ptql);
1689
- #endif
1690
-
1691
- ptql = ptql_copy;
1692
-
1693
- ptql_branch_list_create(&query->branches);
1694
-
1695
- do {
1696
- ptql_parse_branch_t parsed;
1697
-
1698
- if ((ptr = strchr(ptql, ','))) {
1699
- *ptr = '\0';
1700
- }
1701
-
1702
- status = ptql_branch_parse(ptql, &parsed, error);
1703
- if (status == SIGAR_OK) {
1704
- status =
1705
- ptql_branch_add(&parsed, &query->branches, error);
1706
-
1707
- if (status != SIGAR_OK) {
1708
- break;
1709
- }
1710
- if (parsed.op_flags & PTQL_OP_FLAG_REF) {
1711
- has_ref = 1;
1712
- }
1713
- }
1714
- else {
1715
- break;
1716
- }
1717
-
1718
- if (ptr) {
1719
- ptql = ++ptr;
1720
- }
1721
- else {
1722
- break;
1723
- }
1724
- } while (*ptql);
1725
-
1726
- free(ptql_copy);
1727
-
1728
- if (status != SIGAR_OK) {
1729
- sigar_ptql_query_destroy(query);
1730
- *queryp = NULL;
1731
- }
1732
- else if (!has_ref && (query->branches.number > 1)) {
1733
- qsort(query->branches.data,
1734
- query->branches.number,
1735
- sizeof(query->branches.data[0]),
1736
- ptql_branch_compare);
1737
- }
1738
-
1739
- if (status == SIGAR_OK) {
1740
- (void)ptql_error(error, "OK");
1741
- }
1742
- return status;
1743
- }
1744
-
1745
- SIGAR_DECLARE(int) sigar_ptql_query_destroy(sigar_ptql_query_t *query)
1746
- {
1747
- #ifdef PTQL_DEBUG
1748
- free(query->ptql);
1749
- #endif
1750
- ptql_branch_list_destroy(&query->branches);
1751
- free(query);
1752
- return SIGAR_OK;
1753
- }
1754
-
1755
- SIGAR_DECLARE(void) sigar_ptql_re_impl_set(sigar_t *sigar, void *data,
1756
- sigar_ptql_re_impl_t impl)
1757
- {
1758
- sigar->ptql_re_data = data;
1759
- sigar->ptql_re_impl = impl;
1760
- }
1761
-
1762
- SIGAR_DECLARE(int) sigar_ptql_query_match(sigar_t *sigar,
1763
- sigar_ptql_query_t *query,
1764
- sigar_pid_t query_pid)
1765
- {
1766
- int i;
1767
-
1768
- for (i=0; i<query->branches.number; i++) {
1769
- sigar_pid_t pid = query_pid;
1770
- int status, matched=0;
1771
- ptql_branch_t *branch = &query->branches.data[i];
1772
- ptql_lookup_t *lookup = branch->lookup;
1773
-
1774
- if (branch->op_flags & PTQL_OP_FLAG_PARENT) {
1775
- sigar_proc_state_t state;
1776
-
1777
- status = sigar_proc_state_get(sigar, pid, &state);
1778
- if (status != SIGAR_OK) {
1779
- return status;
1780
- }
1781
-
1782
- pid = state.ppid;
1783
- }
1784
-
1785
- if (lookup->type == PTQL_VALUE_TYPE_ANY) {
1786
- /* Args, Env, etc. */
1787
- status = lookup->get(sigar, pid, branch);
1788
- if (status == SIGAR_OK) {
1789
- matched = 1;
1790
- }
1791
- }
1792
- else {
1793
- /* standard sigar_proc_*_get / structptr + offset */
1794
- if (!branch->data.ptr) {
1795
- branch->data_size = lookup->data_size;
1796
- branch->data.ptr = malloc(branch->data_size);
1797
- }
1798
- status = lookup->get(sigar, pid, branch->data.ptr);
1799
- if (status != SIGAR_OK) {
1800
- return status;
1801
- }
1802
-
1803
- if (branch->op_flags & PTQL_OP_FLAG_REF) {
1804
- ptql_branch_t *ref =
1805
- &query->branches.data[branch->value.ui32];
1806
-
1807
- matched = ptql_branch_match_ref(branch, ref);
1808
- }
1809
- #ifndef SIGAR_HAS_PCRE
1810
- else if (branch->lookup->type == PTQL_VALUE_TYPE_STR) {
1811
- matched = ptql_str_match(sigar, branch, (char *)DATA_PTR(branch));
1812
- }
1813
- #endif
1814
- else {
1815
- matched = ptql_branch_match(branch);
1816
- }
1817
- }
1818
-
1819
- if (!matched) {
1820
- return 1;
1821
- }
1822
- }
1823
-
1824
- return SIGAR_OK;
1825
- }
1826
-
1827
- static int ptql_proc_list_get(sigar_t *sigar,
1828
- sigar_ptql_query_t *query,
1829
- sigar_proc_list_t **proclist)
1830
- {
1831
- int status;
1832
- int i;
1833
-
1834
- *proclist = NULL;
1835
-
1836
- for (i=0; i<query->branches.number; i++) {
1837
- ptql_branch_t *branch = &query->branches.data[i];
1838
-
1839
- if (branch->op_flags & PTQL_OP_FLAG_PID) {
1840
- /* pre-filter pid list for Pid.* queries */
1841
- /* XXX multiple Pid.* may result in dups */
1842
- if (*proclist == NULL) {
1843
- *proclist = malloc(sizeof(**proclist));
1844
- SIGAR_ZERO(*proclist);
1845
- sigar_proc_list_create(*proclist);
1846
- }
1847
- status = ptql_pid_list_get(sigar, branch, *proclist);
1848
- if (status != SIGAR_OK) {
1849
- sigar_proc_list_destroy(sigar, *proclist);
1850
- free(*proclist);
1851
- return status;
1852
- }
1853
- }
1854
- }
1855
-
1856
- if (*proclist) {
1857
- return SIGAR_OK;
1858
- }
1859
-
1860
- status = sigar_proc_list_get(sigar, NULL);
1861
- if (status != SIGAR_OK) {
1862
- return status;
1863
- }
1864
- *proclist = sigar->pids;
1865
- return SIGAR_OK;
1866
- }
1867
-
1868
- static int ptql_proc_list_destroy(sigar_t *sigar,
1869
- sigar_proc_list_t *proclist)
1870
- {
1871
- if (proclist != sigar->pids) {
1872
- sigar_proc_list_destroy(sigar, proclist);
1873
- free(proclist);
1874
- }
1875
-
1876
- return SIGAR_OK;
1877
- }
1878
-
1879
- SIGAR_DECLARE(int) sigar_ptql_query_find_process(sigar_t *sigar,
1880
- sigar_ptql_query_t *query,
1881
- sigar_pid_t *pid)
1882
- {
1883
- int status;
1884
- int i, matches=0;
1885
- sigar_proc_list_t *pids;
1886
-
1887
- status = ptql_proc_list_get(sigar, query, &pids);
1888
- if (status != SIGAR_OK) {
1889
- return status;
1890
- }
1891
-
1892
- for (i=0; i<pids->number; i++) {
1893
- int query_status =
1894
- sigar_ptql_query_match(sigar, query, pids->data[i]);
1895
-
1896
- if (query_status == SIGAR_OK) {
1897
- *pid = pids->data[i];
1898
- matches++;
1899
- }
1900
- else if (query_status == SIGAR_ENOTIMPL) {
1901
- /* let caller know query is invalid. */
1902
- status = query_status;
1903
- break;
1904
- } /* else ok, e.g. permission denied */
1905
- }
1906
-
1907
- ptql_proc_list_destroy(sigar, pids);
1908
-
1909
- if (status != SIGAR_OK) {
1910
- return status;
1911
- }
1912
-
1913
- if (matches == 1) {
1914
- return SIGAR_OK;
1915
- }
1916
- else if (matches == 0) {
1917
- sigar_strerror_set(sigar,
1918
- "Query did not match any processes");
1919
- }
1920
- else {
1921
- sigar_strerror_printf(sigar,
1922
- "Query matched multiple processes (%d)",
1923
- matches);
1924
- }
1925
-
1926
- return -1;
1927
- }
1928
-
1929
- SIGAR_DECLARE(int) sigar_ptql_query_find(sigar_t *sigar,
1930
- sigar_ptql_query_t *query,
1931
- sigar_proc_list_t *proclist)
1932
- {
1933
- int status;
1934
- int i;
1935
- sigar_proc_list_t *pids;
1936
-
1937
- status = ptql_proc_list_get(sigar, query, &pids);
1938
- if (status != SIGAR_OK) {
1939
- return status;
1940
- }
1941
-
1942
- sigar_proc_list_create(proclist);
1943
-
1944
- for (i=0; i<pids->number; i++) {
1945
- int query_status =
1946
- sigar_ptql_query_match(sigar, query, pids->data[i]);
1947
-
1948
- if (query_status == SIGAR_OK) {
1949
- SIGAR_PROC_LIST_GROW(proclist);
1950
- proclist->data[proclist->number++] = pids->data[i];
1951
- }
1952
- else if (query_status == SIGAR_ENOTIMPL) {
1953
- /* let caller know query is invalid. */
1954
- status = query_status;
1955
- break;
1956
- }
1957
- }
1958
-
1959
- ptql_proc_list_destroy(sigar, pids);
1960
-
1961
- if (status != SIGAR_OK) {
1962
- sigar_proc_list_destroy(sigar, proclist);
1963
- return status;
1964
- }
1965
-
1966
- return SIGAR_OK;
1967
- }