1 /***********************************************************************
2 * pmie.c - performance inference engine
3 ***********************************************************************
4 *
5 * Copyright (c) 1995-2003 Silicon Graphics, Inc. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 /*
19 * pmie debug flags:
20 * APPL0 - lexical scanning
21 * APPL1 - parse/expression tree construction
22 * APPL2 - expression execution
23 */
24
25 #include <ctype.h>
26 #include <limits.h>
27 #include "pmapi.h"
28 #include "impl.h"
29 #include <sys/stat.h>
30
31 #include "dstruct.h"
32 #include "stomp.h"
33 #include "syntax.h"
34 #include "pragmatics.h"
35 #include "eval.h"
36 #include "show.h"
37
38 #if HAVE_TRACE_BACK_STACK
39 #define MAX_PCS 30 /* max callback procedure depth */
40 #define MAX_SIZE 48 /* max function name length */
41 #include <libexc.h>
42 #endif
43
44
45 /***********************************************************************
46 * constants
47 ***********************************************************************/
48
49 #define LINE_LENGTH 255 /* max length of command token */
50 #define PROC_FNAMESIZE 20 /* from proc pmda - proc.h */
51 #define PMIE_PATHSIZE (sizeof(PMIE_DIR)+PROC_FNAMESIZE)
52
53 static char *prompt = "pmie> ";
54 static char *intro = "Performance Co-Pilot Inference Engine (pmie), "
55 "Version %s\n\n%s%s";
56 char *clientid;
57
58 static FILE *logfp;
59 static char logfile[MAXPATHLEN+1];
60 static char perffile[PMIE_PATHSIZE]; /* /var/tmp/<pid> file name */
61
62 static char menu[] =
63 "pmie debugger commands\n\n"
64 " f [file-name] - load expressions from given file or stdin\n"
65 " l [expr-name] - list named expression or all expressions\n"
66 " r [interval] - run for given or default interval\n"
67 " S time-spec - set start time for run\n"
68 " T time-spec - set default interval for run command\n"
69 " v [expr-name] - print subexpression used for %h, %i and\n"
70 " %v bindings\n"
71 " h or ? - print this menu of commands\n"
72 " q - quit\n\n";
73
74 static char usage[] =
75 "Usage: %s [options] [filename ...]\n\n"
76 "Options:\n"
77 " -A align align sample times on natural boundaries\n"
78 " -a archive metrics source is a PCP log archive\n"
79 " -b one line buffered output stream, stdout on stderr\n"
80 " -C parse configuration and exit\n"
81 " -c filename configuration file\n"
82 " -d interactive debugging mode\n"
83 " -e force timestamps to be reported when used with -V, -v or -W\n"
84 " -f run in foreground\n"
85 " -H do not do a name lookup on the default hostname\n"
86 " -h host metrics source is PMCD on host\n"
87 " -j stompfile stomp protocol (JMS) file [default %s%cconfig%cpmie%cstomp]\n"
88 " -l logfile send status and error messages to logfile\n"
89 " -n pmnsfile use an alternative PMNS\n"
90 " -O offset initial offset into the time window\n"
91 " -S starttime start of the time window\n"
92 " -T endtime end of the time window\n"
93 " -t interval sample interval [default 10 seconds]\n"
94 " -V verbose mode, annotated expression values printed\n"
95 " -v verbose mode, expression values printed\n"
96 " -W verbose mode, satisfying expression values printed\n"
97 " -x run in domain agent mode (summary PMDA)\n"
98 " -Z timezone set reporting timezone\n"
99 " -z set reporting timezone to local time of metrics source\n";
100
101 /***********************************************************************
102 * usage message
103 ***********************************************************************/
104
105 static void
106 usageMessage(void)
107 {
108 int sep = __pmPathSeparator();
109 fprintf(stderr, usage, pmProgname, pmGetConfig("PCP_VAR_DIR"), sep,sep,sep);
110 exit(1);
111 }
112
113
114 /***********************************************************************
115 * interactive commands
116 ***********************************************************************/
117
118 /* read command input line */
119 static int
|
Event noescape: |
"readLine" does not free or save its pointer parameter "bfr". |
120 readLine(char *bfr, int max)
121 {
122 int c, i;
123
124 /* skip blanks */
125 do
126 c = getchar();
127 while (isspace(c));
128
129 /* scan till end of line */
130 i = 0;
131 while ((c != '\n') && (c != EOF) && (i < max)) {
132 bfr[i++] = c;
133 c = getchar();
134 }
135 bfr[i] = '\0';
136 return (c != EOF);
137 }
138
139
140 /* scan interactive command token */
141 static char *
142 scanCmd(char **pp)
143 {
144 char *p = *pp;
145
146 /* skip blanks */
147 while (isspace((int)*p))
148 p++;
149
150 /* single char token */
151 if (isgraph((int)*p)) {
152 *pp = p + 1;
153 return p;
154 }
155
156 return NULL;
157 }
158
159
160 /* scan interactive command argument */
161 static char *
162 scanArg(char *p)
163 {
164 char *q;
165
166 /* strip leading blanks */
167 while (isspace((int)*p))
168 p++;
169 if (*p == '\0')
170 return NULL;
171 q = p;
172
173 /* strip trailing blanks */
174 while (*q != '\0')
175 q++;
176 q--;
177 while (isspace((int)*q))
178 q--;
179 *(q + 1) = '\0';
180
181 /* return result */
182 return p;
183 }
184
185
186 /* load rules from given file or stdin */
187 static void
188 load(char *fname)
189 {
190 Symbol s;
191 Expr *d;
192 int sts = 0;
193 int sep = __pmPathSeparator();
194 char config[MAXPATHLEN+1];
195
196 /* search for configfile on configuration file path */
197 if (fname && access(fname, F_OK) != 0) {
198 sts = oserror(); /* always report the first error */
199 if (__pmAbsolutePath(fname)) {
200 fprintf(stderr, "%s: cannot access config file %s: %s\n", pmProgname,
201 fname, strerror(sts));
202 exit(1);
203 }
204 #if PCP_DEBUG
205 else if (pmDebug & DBG_TRACE_APPL0) {
206 fprintf(stderr, "load: cannot access config file %s: %s\n", fname, strerror(sts));
207 }
208 #endif
209 snprintf(config, sizeof(config), "%s%c" "config" "%c" "pmie" "%c%s",
210 pmGetConfig("PCP_VAR_DIR"), sep, sep, sep, fname);
211 if (access(config, F_OK) != 0) {
212 fprintf(stderr, "%s: cannot access config file as either %s or %s: %s\n",
213 pmProgname, fname, config, strerror(sts));
214 exit(1);
215 }
216 #if PCP_DEBUG
217 else if (pmDebug & DBG_TRACE_APPL0) {
218 fprintf(stderr, "load: using standard config file %s\n", config);
219 }
220 #endif
221 fname = config;
222 }
223 #if PCP_DEBUG
224 else if (pmDebug & DBG_TRACE_APPL0) {
225 fprintf(stderr, "load: using config file %s\n",
226 fname == NULL? "<stdin>":fname);
227 }
228 #endif
229
230 if (perf->config[0] == '\0') { /* keep record of first config */
231 if (fname == NULL)
232 strcpy(perf->config, "<stdin>");
233 else if (realpath(fname, perf->config) == NULL) {
234 fprintf(stderr, "%s: failed to resolve realpath for %s: %s\n",
235 pmProgname, fname, osstrerror());
236 exit(1);
237 }
238 }
239
240 if (synInit(fname)) {
241 while ((s = syntax()) != NULL) {
242 d = (Expr *) symValue(symDelta);
243 pragmatics(s, *(RealTime *)d->smpls[0].ptr);
244 }
245 }
246 }
247
248
249 /* list given expression or all expressions */
250 static void
251 list(char *name)
252 {
253 Task *t;
254 Symbol *r;
255 Symbol s;
256 int i;
257
258 if (name) { /* single named rule */
259 if ( (s = symLookup(&rules, name)) )
260 showSyntax(stdout, s);
261 else
262 printf("%s: error - rule \"%s\" not defined\n", pmProgname, name);
263 }
264 else { /* all rules */
265 t = taskq;
266 while (t) {
267 r = t->rules;
268 for (i = 0; i < t->nrules; i++) {
269 showSyntax(stdout, *r);
270 r++;
271 }
272 t = t->next;
273 }
274 }
275 }
276
277
278 /* list binding subexpression of given expression or all expressions */
279 static void
280 sublist(char *name)
281 {
282 Task *t;
283 Symbol *r;
284 Symbol s;
285 int i;
286
287 if (name) { /* single named rule */
288 if ( (s = symLookup(&rules, name)) )
289 showSubsyntax(stdout, s);
290 else
291 printf("%s: error - rule '%s' not defined\n", pmProgname, name);
292 }
293 else { /* all rules */
294 t = taskq;
295 while (t) {
296 r = t->rules;
297 for (i = 0; i < t->nrules; i++) {
298 showSubsyntax(stdout, *r);
299 r++;
300 }
301 t = t->next;
302 }
303 }
304 }
305
306
307 /***********************************************************************
308 * manipulate the performance instrumentation data structure
309 ***********************************************************************/
310
311 static void
312 stopmonitor(void)
313 {
314 if (*perffile)
315 unlink(perffile);
316 }
317
318 static void
319 startmonitor(void)
320 {
321 struct hostent *hep = noDnsFlag ? NULL : gethostbyname(dfltHost);
322 void *ptr;
323 int fd;
324 char zero = '\0';
325
326 /* try to create the port file directory. OK if it already exists */
327 if ( (mkdir2(PMIE_DIR, S_IRWXU | S_IRWXG | S_IRWXO) < 0) &&
328 (oserror() != EEXIST) ) {
329 fprintf(stderr, "%s: error creating stats file dir %s: %s\n",
330 pmProgname, PMIE_DIR, osstrerror());
331 exit(1);
332 }
333
334 chmod(PMIE_DIR, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
335 atexit(stopmonitor);
336
337 /* create and initialize memory mapped performance data file */
338 sprintf(perffile, "%s%c%" FMT_PID, PMIE_DIR, __pmPathSeparator(), getpid());
339 unlink(perffile);
340 if ((fd = open(perffile, O_RDWR | O_CREAT | O_EXCL | O_TRUNC,
341 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
342 fprintf(stderr, "%s: cannot create stats file %s: %s\n",
343 pmProgname, perffile, osstrerror());
344 exit(1);
345 }
346 /* seek to struct size and write one zero */
347 lseek(fd, sizeof(pmiestats_t)-1, SEEK_SET);
348 if (write(fd, &zero, 1) != 1) {
349 fprintf(stderr, "%s: Warning: write failed for stats file %s: %s\n",
350 pmProgname, perffile, osstrerror());
351 }
352
353 /* map perffile & associate the instrumentation struct with it */
354 if ((ptr = __pmMemoryMap(fd, sizeof(pmiestats_t), 1)) == NULL) {
355 fprintf(stderr, "%s: memory map failed for stats file %s: %s\n",
356 pmProgname, perffile, osstrerror());
357 exit(1);
358 }
359 close(fd);
360
361 perf = (pmiestats_t *)ptr;
362 strcpy(perf->logfile, logfile[0] == '\0'? "<none>" : logfile);
363 strcpy(perf->defaultfqdn, hep == NULL? dfltHost : hep->h_name);
364 perf->version = 1;
365 }
366
367
368 /***********************************************************************
369 * signal handling
370 ***********************************************************************/
371
372 static void
373 sigintproc(int sig)
374 {
375 __pmSetSignalHandler(SIGINT, SIG_IGN);
376 __pmSetSignalHandler(SIGTERM, SIG_IGN);
377 __pmNotifyErr(LOG_INFO, "%s caught SIGINT or SIGTERM\n", pmProgname);
378 exit(1);
379 }
380
381 static void
382 sigbye(int sig)
383 {
384 exit(0);
385 }
386
387 static void
388 remap_stdout_stderr(void)
389 {
390 int i, j;
391
392 fflush(stderr);
393 fflush(stdout);
394 setlinebuf(stderr);
395 setlinebuf(stdout);
396 i = fileno(stdout);
397 close(i);
398 if ((j = dup(fileno(stderr))) != i)
399 fprintf(stderr, "%s: Warning: failed to link stdout ... "
400 "dup() returns %d, expected %d (stderr=%d)\n",
401 pmProgname, j, i, fileno(stderr));
402 }
403
404 static void
405 sighupproc(int sig)
406 {
407 FILE *fp;
408 int sts;
409
410 fp = __pmRotateLog(pmProgname, logfile, logfp, &sts);
411 if (sts != 0) {
412 fprintf(stderr, "pmie: PID = %" FMT_PID ", default host = %s\n\n",
413 getpid(), dfltHost);
414 remap_stdout_stderr();
415 logfp = fp;
416 } else {
417 __pmNotifyErr(LOG_ERR, "pmie: log rotation failed\n");
418 }
419 }
420
421
422 static void
423 dotraceback(void)
424 {
425 #if HAVE_TRACE_BACK_STACK
426 __uint64_t call_addr[MAX_PCS];
427 char *call_fn[MAX_PCS];
428 char names[MAX_PCS][MAX_SIZE];
429 int res;
430 int i;
431
432 fprintf(stderr, "\nProcedure call traceback ...\n");
433 for (i = 0; i < MAX_PCS; i++)
434 call_fn[i] = names[i];
435 res = trace_back_stack(MAX_PCS, call_addr, call_fn, MAX_PCS, MAX_SIZE);
436 for (i = 1; i < res; i++)
437 fprintf(stderr, " " PRINTF_P_PFX "%p [%s]\n", (void *)call_addr[i], call_fn[i]);
438 #endif
439 return;
440 }
441
442 static void
443 sigbadproc(int sig)
444 {
445 __pmNotifyErr(LOG_ERR, "Unexpected signal %d ...\n", sig);
446 dotraceback();
447 fprintf(stderr, "\nDumping to core ...\n");
448 fflush(stderr);
449 stopmonitor();
450 abort();
451 }
452
453
454 /***********************************************************************
455 * command line processing - extract command line arguments & initialize
456 ***********************************************************************/
457
458 static void
459 getargs(int argc, char *argv[])
460 {
461 char *configfile = NULL;
462 char *commandlog = NULL;
463 char *subopts;
464 char *subopt;
465 char *msg;
466 int checkFlag = 0;
467 int foreground = 0;
468 int err = 0;
469 int sts;
470 int c;
471 int bflag = 0;
472 Archive *a;
473 struct timeval tv, tv1, tv2;
474 extern int showTimeFlag;
475 extern int errs; /* syntax errors from syntax.c */
476
477 memset(&tv, 0, sizeof(tv));
478 memset(&tv1, 0, sizeof(tv1));
479 memset(&tv2, 0, sizeof(tv2));
480 dstructInit();
481
482 while ((c=getopt(argc, argv, "a:A:bc:CdD:efHh:j:l:n:O:S:t:T:vVWXxzZ:?")) != EOF) {
483 switch (c) {
484
485 case 'a': /* archives */
486 if (dfltConn && dfltConn != PM_CONTEXT_ARCHIVE) {
487 fprintf(stderr, "%s: at most one of -a or -h allowed\n",
488 pmProgname);
489 err++;
490 break;
491 }
492 dfltConn = PM_CONTEXT_ARCHIVE;
493 subopts = optarg;
494 for ( ; ; ) {
495 subopt = subopts;
496 subopts = strchr(subopts, ',');
497 if (subopts != NULL) {
498 *subopts++ = '\0';
499 }
500 a = (Archive *) zalloc(sizeof(Archive));
501 a->fname = subopt;
502 if (!initArchive(a)) {
503 exit(1);
504 }
505 if (subopts == NULL) break;
506 }
507 foreground = 1;
508 break;
509
510 case 'A': /* sample alignment */
511 alignFlag = optarg;
512 break;
513
514 case 'b': /* line buffered, stdout on stderr */
515 bflag++;
516 break;
517
518 case 'c': /* configuration file */
519 if (interactive) {
520 fprintf(stderr, "%s: at most one of -c and -d allowed\n",
521 pmProgname);
522 err++;
523 break;
524 }
525 configfile = optarg;
526 break;
527
528 case 'C': /* check config and exit */
529 checkFlag = 1;
530 break;
531
532 case 'd': /* interactive mode */
533 if (configfile) {
534 fprintf(stderr, "%s: at most one of -c and -d allowed\n",
535 pmProgname);
536 err++;
537 break;
538 }
539 interactive = 1;
540 break;
541
542 case 'D': /* debug flag */
543 sts = __pmParseDebug(optarg);
544 if (sts < 0) {
545 fprintf(stderr, "%s: unrecognized debug flag specification "
546 "(%s)\n", pmProgname, optarg);
547 err++;
548 }
549 else
550 pmDebug |= sts;
551 break;
552
553 case 'e': /* force timestamps */
554 showTimeFlag = 1;
555 break;
556
557 case 'f': /* in foreground, not as daemon */
558 foreground = 1;
559 break;
560
561 case 'H': /* no name lookup on exported host */
562 noDnsFlag = 1;
563 break;
564
565 case 'h': /* default host name */
566 if (dfltConn) {
567 fprintf(stderr, "%s: at most one of -a or -h allowed\n",
568 pmProgname);
569 err++;
570 break;
571 }
572 dfltConn = PM_CONTEXT_HOST;
573 dfltHost = optarg;
574 break;
575
576 case 'j': /* stomp protocol (JMS) config */
577 stompfile = optarg;
578 break;
579
580 case 'l': /* alternate log file */
581 if (commandlog != NULL) {
582 fprintf(stderr, "%s: at most one -l option is allowed\n",
583 pmProgname);
584 err++;
585 break;
586 }
587 commandlog = optarg;
588 isdaemon = 1;
589 break;
590
591 case 'n': /* alternate namespace file */
592 pmnsfile = optarg;
593 break;
594
595 case 'O': /* position within time window */
596 offsetFlag = optarg;
597 break;
598
599 case 'S': /* start run time */
600 startFlag = optarg;
601 break;
602
603 case 't': /* sample interval */
604 if (pmParseInterval(optarg, &tv1, &msg) == 0)
605 dfltDelta = realize(tv1);
606 else {
607 fprintf(stderr, "%s: could not parse -t argument (%s)\n", pmProgname, optarg);
608 fputs(msg, stderr);
609 free(msg);
610 err++;
611 }
612 break;
613
614 case 'T': /* evaluation period */
615 stopFlag = optarg;
616 break;
617
618 case 'v': /* print values */
619 verbose = 1;
620 break;
621
622 case 'V': /* print annotated values */
623 verbose = 2;
624 break;
625
626 case 'W': /* print satisfying values */
627 verbose = 3;
628 break;
629
630 case 'X': /* secret applet flag */
631 applet = 1;
632 verbose = 1;
633 setlinebuf(stdout);
634 break;
635
636 case 'x': /* summary PMDA flag */
637 agent = 1;
638 verbose = 1;
639 isdaemon = 1;
640 break;
641
642 case 'z': /* timezone from host */
643 hostZone = 1;
644 if (timeZone) {
645 fprintf(stderr, "%s: only one of -Z and -z allowed\n",
646 pmProgname);
647 err++;
648 }
649 break;
650
651 case 'Z': /* explicit TZ string */
652 timeZone = optarg;
653 if (hostZone) {
654 fprintf(stderr, "%s: only one of -Z and -z allowed\n",
655 pmProgname);
656 err++;
657 }
658 break;
659
660 case '?':
661 err++;
662 }
663 }
664
665 if (configfile && optind != argc) {
666 fprintf(stderr, "%s: extra filenames cannot be given after using -c\n",
667 pmProgname);
668 err++;
669 }
670 if (bflag && agent) {
671 fprintf(stderr, "%s: the -b and -x options are incompatible\n",
672 pmProgname);
673 err++;
674 }
675 if (err)
676 usageMessage();
677
678 if (foreground)
679 isdaemon = 0;
680
681 if (archives || interactive)
682 perf = &instrument;
683
684 if (isdaemon) { /* daemon mode */
685 #if defined(HAVE_TERMIO_SIGNALS)
686 signal(SIGTTOU, SIG_IGN);
687 signal(SIGTTIN, SIG_IGN);
688 signal(SIGTSTP, SIG_IGN);
689 #endif
690 __pmSetSignalHandler(SIGINT, sigintproc);
691 __pmSetSignalHandler(SIGTERM, sigintproc);
692 __pmSetSignalHandler(SIGBUS, sigbadproc);
693 __pmSetSignalHandler(SIGSEGV, sigbadproc);
694 }
695 else {
696 /* need to catch these so the atexit() processing is done */
697 __pmSetSignalHandler(SIGINT, sigbye);
698 __pmSetSignalHandler(SIGTERM, sigbye);
699 }
700
701 if (commandlog != NULL) {
702 logfp = __pmOpenLog(pmProgname, commandlog, stderr, &sts);
703 if (realpath(commandlog, logfile) == NULL) {
704 fprintf(stderr, "%s: cannot find realpath for log %s: %s\n",
705 pmProgname, commandlog, osstrerror());
706 exit(1);
707 }
708 __pmSetSignalHandler(SIGHUP, (isdaemon && !agent) ? sighupproc : SIG_IGN);
709 } else {
710 __pmSetSignalHandler(SIGHUP, SIG_IGN);
711 }
712
713 /*
714 * -b ... force line buffering and stdout onto stderr
715 */
716 if ((bflag || isdaemon) && !agent)
717 remap_stdout_stderr();
718
719 if (dfltConn == 0) {
720 /* default case, no -a or -h */
721 dfltConn = PM_CONTEXT_HOST;
722 dfltHost = localHost;
723 }
724
725 if (!archives && !interactive) {
726 if (commandlog != NULL)
727 fprintf(stderr, "pmie: PID = %" FMT_PID ", default host = %s\n\n", getpid(), dfltHost);
728 startmonitor();
729 }
730
731 /* default host from leftmost archive on command line */
732 if (archives && dfltHost == localHost) {
733 a = archives;
734 while (a->next)
735 a = a->next;
736 dfltHost = a->hname;
737 }
738
739 /* initialize time */
740 now = archives ? first : getReal() + 1.0;
741 zoneInit();
742 reflectTime(dfltDelta);
743
744 /* parse time window - just to check argument syntax */
745 unrealize(now, &tv1);
746 if (archives)
747 unrealize(last, &tv2);
748 else
749 tv2.tv_sec = INT_MAX; /* sizeof(time_t) == sizeof(int) */
750 if (pmParseTimeWindow(startFlag, stopFlag, alignFlag, offsetFlag,
751 &tv1, &tv2,
752 &tv, &tv2, &tv1,
753 &msg) < 0) {
754 fputs(msg, stderr);
755 exit(1);
756 }
757 start = realize(tv1);
758 stop = realize(tv2);
759 runTime = stop - start;
760
761 /* initialize PMAPI */
762 if (pmnsfile != PM_NS_DEFAULT && (sts = pmLoadNameSpace(pmnsfile)) < 0) {
763 fprintf(stderr, "%s: pmLoadNameSpace failed: %s\n", pmProgname,
764 pmErrStr(sts));
765 exit(1);
766 }
767
768 /* when not in secret agent mode, register client id with pmcd */
769 if (!agent)
770 clientid = __pmGetClientId(argc, argv);
771
772 if (!interactive && optind == argc) { /* stdin or config file */
773 load(configfile);
774 }
775 else { /* list of 1/more filenames */
776 while (optind < argc) {
777 load(argv[optind]);
778 optind++;
779 }
780 }
781
782 #if PCP_DEBUG
783 if (pmDebug & DBG_TRACE_APPL1)
784 dumpRules();
785 #endif
786
787 if (checkFlag)
788 exit(errs == 0 ? 0 : 1); /* exit 1 for syntax errors ...
789 * suggestion from
790 * Kevin Wang <kjw@rightsock.com>
791 */
792
793 if (isdaemon) { /* daemon mode */
794 /* Note: we can no longer unilaterally close stdin here, as it
795 * can really confuse remap_stdout_stderr() during log rotation!
796 */
797 if (agent)
798 close(fileno(stdin));
799 #ifndef IS_MINGW
800 setsid(); /* not process group leader, lose controlling tty */
801 #endif
802 }
803
804 if (stomping)
805 stompInit(); /* connect to our message server */
806
807 if (agent)
808 agentInit(); /* initialize secret agent stuff */
809
810 /* really parse time window */
811 if (!archives) {
812 now = getReal() + 1.0;
813 reflectTime(dfltDelta);
814 }
815 unrealize(now, &tv1);
816 if (archives)
817 unrealize(last, &tv2);
818 else
819 tv2.tv_sec = INT_MAX;
820 if (pmParseTimeWindow(startFlag, stopFlag, alignFlag, offsetFlag,
821 &tv1, &tv2,
822 &tv, &tv2, &tv1,
823 &msg) < 0) {
824 fputs(msg, stderr);
825 exit(1);
826 }
827
828 /* set run timing window */
829 start = realize(tv1);
830 stop = realize(tv2);
831 runTime = stop - start;
832 }
833
834 /***********************************************************************
835 * interactive (debugging) mode
836 ***********************************************************************/
837
838 static void
839 interact(void)
840 {
841 int quit = 0;
|
Event alloc_fn: |
Calling allocation function "zalloc". [details] |
|
Event var_assign: |
Assigning: "line" = storage returned from "zalloc(257UL)". |
| Also see events: |
[noescape][leaked_storage] |
842 char *line = (char *) zalloc(LINE_LENGTH + 2);
843 char *finger;
844 char *token;
845 char *msg;
846 RealTime rt;
847 struct timeval tv1, tv2;
848
849 printf(intro, PCP_VERSION, menu, prompt);
850 fflush(stdout);
|
At conditional (1): "!quit": Taking true branch.
|
|
At conditional (2): "readLine(line, 255)": Taking false branch.
|
851 while (!quit && readLine(line, LINE_LENGTH)) {
852 finger = line;
853
854 if ( (token = scanCmd(&finger)) ) {
855 switch (*token) {
856
857 case 'f':
858 token = scanArg(finger);
859 load(token);
860 break;
861
862 case 'l':
863 token = scanArg(finger);
864 list(token);
865 break;
866
867 case 'r':
868 token = scanArg(finger);
869 if (token) {
870 if (pmParseInterval(token, &tv1, &msg) == 0)
871 runTime = realize(tv1);
872 else {
873 fputs(msg, stderr);
874 free(msg);
875 break;
876 }
877 }
878 if (!archives) {
879 invalidate();
880 rt = getReal();
881 if (now < rt)
882 now = rt;
883 start = now;
884 }
885 stop = start + runTime;
886 run();
887 break;
888
889 case 'S':
890 token = scanArg(finger);
891 if (token == NULL) {
892 fprintf(stderr, "%s: error - argument required\n", pmProgname);
893 break;
894 }
895 unrealize(start, &tv1);
896 if (archives)
897 unrealize(last, &tv2);
898 else
899 tv2.tv_sec = INT_MAX;
900 if (__pmParseTime(token, &tv1, &tv2, &tv1, &msg) < 0) {
901 fputs(msg, stderr);
902 free(msg);
903 break;
904 }
905 start = realize(tv1);
906 if (archives)
907 invalidate();
908 break;
909
910 case 'T':
911 token = scanArg(finger);
912 if (token == NULL) {
913 fprintf(stderr, "%s: error - argument required\n", pmProgname);
914 break;
915 }
916 if (pmParseInterval(token, &tv1, &msg) < 0) {
917 fputs(msg, stderr);
918 free(msg);
919 break;
920 }
921 runTime = realize(tv1);
922 break;
923 case 'q':
924 quit = 1;
925 break;
926
927 case 'v':
928 token = scanArg(finger);
929 sublist(token);
930 break;
931
932 case '?':
933 default:
934 printf("%s", menu);
935 }
936 }
937 if (!quit) {
938 printf("%s", prompt);
939 fflush(stdout);
940 }
941 }
|
Event leaked_storage: |
Variable "line" going out of scope leaks the storage it points to. |
| Also see events: |
[alloc_fn][var_assign][noescape] |
942 }
943
944
945 /***********************************************************************
946 * main
947 ***********************************************************************/
948
949 int
950 main(int argc, char **argv)
951 {
952 __pmSetProgname(argv[0]);
953 setlinebuf(stdout);
954
955 /* PCP_COUNTER_WRAP in environment enables "counter wrap" logic */
956 if (getenv("PCP_COUNTER_WRAP") != NULL)
957 dowrap = 1;
958
959 getargs(argc, argv);
960
961 if (interactive)
962 interact();
963 else
964 run();
965 exit(0);
966 }