1 /*-
2 ***********************************************************************
3 *
4 * $Id: ftimes.c,v 1.62 2014/07/18 06:40:44 mavrik Exp $
5 *
6 ***********************************************************************
7 *
8 * Copyright 2000-2014 The FTimes Project, All Rights Reserved.
9 *
10 ***********************************************************************
11 */
12 #include "all-includes.h"
13
14 #ifdef USE_EMBEDDED_PERL
15 /*-
16 ***********************************************************************
17 *
18 * Glue code for embedded Perl (taken from perlembed.pod).
19 *
20 ***********************************************************************
21 */
22 EXTERN_C void xs_init (pTHX);
23 EXTERN_C void boot_DynaLoader (pTHX_ CV *cv);
24
25 EXTERN_C void
xs_init(pTHX)26 xs_init(pTHX)
27 {
28 char *pcFile = __FILE__;
29
30 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, pcFile);
31 }
32 #endif
33
34 /*-
35 ***********************************************************************
36 *
37 * Global variables
38 *
39 ***********************************************************************
40 */
41 static FTIMES_PROPERTIES *gpsProperties;
42
43 #ifdef WINNT
44 HINSTANCE NtdllHandle;
45 NQIF NtdllNQIF;
46 #endif
47
48 /*-
49 ***********************************************************************
50 *
51 * Main
52 *
53 ***********************************************************************
54 */
55 int
main(int iArgumentCount,char * ppcArgumentVector[])56 main(int iArgumentCount, char *ppcArgumentVector[])
57 {
58 const char acRoutine[] = "Main()";
59 char aacLocalError[2][MESSAGE_SIZE];
60 FTIMES_PROPERTIES *psProperties;
61 int iError;
62
63 aacLocalError[0][0] = aacLocalError[1][0] = 0;
64
65 iError = FTimesBootstrap(aacLocalError[1]);
66 if (iError != ER_OK)
67 {
68 snprintf(aacLocalError[0], MESSAGE_SIZE, "%s: %s", acRoutine, aacLocalError[1]);
69 ErrorHandler(XER_BootStrap, aacLocalError[0], ERROR_CRITICAL);
70 }
71 psProperties = FTimesGetPropertiesReference();
72
73 iError = FTimesProcessArguments(psProperties, iArgumentCount, ppcArgumentVector, aacLocalError[1]);
74 if (iError != ER_OK)
75 {
76 snprintf(aacLocalError[0], MESSAGE_SIZE, "%s: %s", acRoutine, aacLocalError[1]);
77 ErrorHandler(XER_ProcessArguments, aacLocalError[0], ERROR_CRITICAL);
78 }
79
80 iError = FTimesFinalize(psProperties, aacLocalError[1]);
81 if (iError != ER_OK)
82 {
83 snprintf(aacLocalError[0], MESSAGE_SIZE, "%s: %s", acRoutine, aacLocalError[1]);
84 ErrorHandler(XER_Finalize, aacLocalError[0], ERROR_CRITICAL);
85 }
86
87 if (psProperties->iLastRunModeStage > 0)
88 {
89 iError = FTimesStagesLoop(psProperties, aacLocalError[1]);
90 if (iError != ER_OK)
91 {
92 snprintf(aacLocalError[0], MESSAGE_SIZE, "%s: %s", acRoutine, aacLocalError[1]);
93 ErrorHandler(iError, aacLocalError[0], ERROR_CRITICAL);
94 }
95 }
96
97 iError = FTimesFinalStage(psProperties, aacLocalError[1]);
98 if (iError != ER_OK)
99 {
100 snprintf(aacLocalError[0], MESSAGE_SIZE, "%s: %s", acRoutine, aacLocalError[1]);
101 ErrorHandler(XER_FinalStage, aacLocalError[0], ERROR_CRITICAL);
102 }
103
104 return XER_OK;
105 }
106
107
108 /*-
109 ***********************************************************************
110 *
111 * FTimesBootstrap
112 *
113 ***********************************************************************
114 */
115 int
FTimesBootstrap(char * pcError)116 FTimesBootstrap(char *pcError)
117 {
118 const char acRoutine[] = "FTimesBootstrap()";
119 char acLocalError[MESSAGE_SIZE] = "";
120 FTIMES_PROPERTIES *psProperties;
121 #ifdef WINNT
122 char *pcMessage;
123 int iError;
124 #endif
125
126 /*-
127 *********************************************************************
128 *
129 * Require certain truths. If these tests produce an error, there is
130 * something wrong with the code.
131 *
132 *********************************************************************
133 */
134 if (DECODE_FIELD_COUNT != MaskGetTableLength(MASK_RUNMODE_TYPE_CMP))
135 {
136 snprintf(pcError, MESSAGE_SIZE, "%s: DecodeFieldCount/CmpMaskTableSize mismatch!: %d != %d", acRoutine, DECODE_FIELD_COUNT, MaskGetTableLength(MASK_RUNMODE_TYPE_CMP));
137 return ER;
138 }
139
140 if (DECODE_FIELD_COUNT != DecodeGetTableLength())
141 {
142 snprintf(pcError, MESSAGE_SIZE, "%s: DecodeFieldCount/DecodeTableSize mismatch!: %d != %d", acRoutine, DECODE_FIELD_COUNT, DecodeGetTableLength());
143 return ER;
144 }
145
146 if (FTIMES_MAX_LINE != DECODE_MAX_LINE)
147 {
148 snprintf(pcError, MESSAGE_SIZE, "%s: FTimesMaxLine/DecodeMaxLine mismatch!: %d != %d", acRoutine, FTIMES_MAX_LINE, DECODE_MAX_LINE);
149 return ER;
150 }
151
152 if (FTIMES_MAX_LINE != CMP_MAX_LINE)
153 {
154 snprintf(pcError, MESSAGE_SIZE, "%s: FTimesMaxLine/CmpMaxLine mismatch!: %d != %d", acRoutine, FTIMES_MAX_LINE, CMP_MAX_LINE);
155 return ER;
156 }
157
158 /*-
159 *********************************************************************
160 *
161 * Setup the Message Handler's output stream.
162 *
163 *********************************************************************
164 */
165 MessageSetOutputStream(stderr);
166
167 #ifdef WINNT
168 /*-
169 *********************************************************************
170 *
171 * Suppress critical-error-handler message boxes.
172 *
173 *********************************************************************
174 */
175 SetErrorMode(SEM_FAILCRITICALERRORS);
176
177 /*-
178 *********************************************************************
179 *
180 * Put stdout/stderr in binary mode to prevent CRLF mappings.
181 *
182 *********************************************************************
183 */
184 iError = _setmode(_fileno(stdout), _O_BINARY);
185 if (iError == -1)
186 {
187 snprintf(pcError, MESSAGE_SIZE, "%s: _setmode(): stdout: %s", acRoutine, strerror(errno));
188 return ER;
189 }
190
191 iError = _setmode(_fileno(stderr), _O_BINARY);
192 if (iError == -1)
193 {
194 snprintf(pcError, MESSAGE_SIZE, "%s: _setmode(): stderr: %s", acRoutine, strerror(errno));
195 return ER;
196 }
197
198 /*-
199 *********************************************************************
200 *
201 * Load NT's native library, if necessary.
202 *
203 *********************************************************************
204 */
205 if (NtdllHandle == NULL)
206 {
207 NtdllHandle = LoadLibrary("NTdll.dll");
208 if (NtdllHandle == NULL)
209 {
210 ErrorFormatWinxError(GetLastError(), &pcMessage);
211 snprintf(pcError, MESSAGE_SIZE, "%s: LoadLibrary(): Library = [NTdll.dll]: %s", acRoutine, pcMessage);
212 return ER;
213 }
214 }
215
216 if (NtdllNQIF == NULL)
217 {
218 NtdllNQIF = (NQIF) GetProcAddress(NtdllHandle, "NtQueryInformationFile");
219 if (NtdllNQIF == NULL)
220 {
221 FreeLibrary(NtdllHandle);
222 ErrorFormatWinxError(GetLastError(), &pcMessage);
223 snprintf(pcError, MESSAGE_SIZE, "%s: GetProcAddress(): Routine = [NtQueryInformationFile]: %s", acRoutine, pcMessage);
224 return ER;
225 }
226 }
227 #endif
228 #ifdef USE_SSL
229 SslBoot();
230 #endif
231
232 psProperties = FTimesNewProperties(acLocalError);
233 if (psProperties == NULL)
234 {
235 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
236 return ER;
237 }
238 FTimesSetPropertiesReference(psProperties);
239
240 return ER_OK;
241 }
242
243
244 /*-
245 ***********************************************************************
246 *
247 * FTimesFinalize
248 *
249 ***********************************************************************
250 */
251 int
FTimesFinalize(FTIMES_PROPERTIES * psProperties,char * pcError)252 FTimesFinalize(FTIMES_PROPERTIES *psProperties, char *pcError)
253 {
254 const char acRoutine[] = "FTimesFinalize()";
255 char acLocalError[MESSAGE_SIZE] = "";
256 int iError = 0;
257 #ifdef USE_EMBEDDED_PERL
258 char *pacArgumentVector[] = { "", "-e", "0" };
259 char **ppcArgumentVector = pacArgumentVector;
260 int iArgumentCount = 3;
261 int iPerlStatus = 0;
262 char acScriptHandler[] =
263 "\n\
264 use strict; use warnings;\n\
265 \n\
266 ######################################################################\n\
267 #\n\
268 # Redefine CORE::GLOBAL::exit() so that any calls to exit() made from\n\
269 # within Perl scripts or modules won't cause the interpreter to exit,\n\
270 # which would, in turn, cause ftimes to exit as well.\n\
271 #\n\
272 ######################################################################\n\
273 \n\
274 package main;\n\
275 \n\
276 use subs qw(CORE::GLOBAL::exit);\n\
277 \n\
278 sub CORE::GLOBAL::exit { die(qq(ExitCode='$_[0]'\\n)); }\n\
279 \n\
280 ######################################################################\n\
281 #\n\
282 # Embed::Persistent\n\
283 #\n\
284 ######################################################################\n\
285 \n\
286 package Embed::Persistent;\n\
287 \n\
288 use Symbol qw(delete_package);\n\
289 \n\
290 our %hMTimeDeltas;\n\
291 \n\
292 ######################################################################\n\
293 #\n\
294 # EvalScript\n\
295 #\n\
296 ######################################################################\n\
297 \n\
298 sub EvalScript\n\
299 {\n\
300 my ($sScript, @aArgumentVector) = @_;\n\
301 \n\
302 my $sPackageName = LoadScript($sScript);\n\
303 if (!defined($sPackageName))\n\
304 {\n\
305 return undef; # NOTE: $@ is set by LoadScript().\n\
306 }\n\
307 \n\
308 eval { $sPackageName->Worker(@ARGV=@aArgumentVector); };\n\
309 if ($@) # NOTE: $@ becomes ERRSV over in C land.\n\
310 {\n\
311 $@ =~ s/[\\t\\r\\n]+/ /g; $@ =~ s/\\s+/ /g; $@ =~ s/^\\s+//; $@ =~ s/\\s+$//;\n\
312 if ($@ =~ /^ExitCode='(\\d+)'/)\n\
313 {\n\
314 $@ = undef; # The script used the approved exit mechanism (i.e., it called exit() with an integer value), so clear the eval error.\n\
315 return int($1); # Cast the return value as an integer so that it's handled correctly over in C land.\n\
316 }\n\
317 return undef; # This script didn't use the approved exit mechanism or failed for some other reason.\n\
318 }\n\
319 \n\
320 return 0; # The script ran without error, but didn't use the approved exit mechanism.\n\
321 }\n\
322 \n\
323 \n\
324 ######################################################################\n\
325 #\n\
326 # GetPackageName\n\
327 #\n\
328 ######################################################################\n\
329 \n\
330 sub GetPackageName\n\
331 {\n\
332 my $sString = (defined($_[0]) && length($_[0]) > 0) ? $_[0] : qq(anonymous);\n\
333 \n\
334 my @aPackageElements = qw(Embed Persistent);\n\
335 foreach my $sElement (split('/', $sString))\n\
336 {\n\
337 next unless (defined($sElement) && length($sElement) > 0);\n\
338 $sElement =~ s/([^0-9A-Za-z])/sprintf(qq(_%02x_), unpack('C', $1))/seg;\n\
339 $sElement =~ s/^([0-9])/sprintf(qq(_%02x_), unpack('C', $1))/seg;\n\
340 push(@aPackageElements, $sElement);\n\
341 }\n\
342 \n\
343 return join(qq(::), @aPackageElements);\n\
344 }\n\
345 \n\
346 \n\
347 ######################################################################\n\
348 #\n\
349 # LoadScript\n\
350 # \n\
351 ######################################################################\n\
352 \n\
353 sub LoadScript\n\
354 {\n\
355 my ($sScript) = @_;\n\
356 if (!defined($sScript))\n\
357 {\n\
358 $@ = qq(script not defined);\n\
359 return undef;\n\
360 }\n\
361 my @aPackageElements = qw(Embed Persistent);\n\
362 foreach my $sElement (split(/\\//, $sScript))\n\
363 {\n\
364 next unless (defined($sElement) && length($sElement) > 0);\n\
365 $sElement =~ s/([^0-9A-Za-z])/sprintf(qq(_%02x_), unpack('C', $1))/seg;\n\
366 $sElement =~ s/^(\\d)/sprintf(qq(_%02x_), unpack('C', $1))/seg;\n\
367 push(@aPackageElements, $sElement);\n\
368 }\n\
369 my $sPackageName = join(qq(::), @aPackageElements);\n\
370 \n\
371 if (!-f $sScript || !-r _)\n\
372 {\n\
373 $@ = qq(script does not exist, is not regular, or is unreadable);\n\
374 return undef;\n\
375 }\n\
376 my $sMTimeDelta = -M $sScript;\n\
377 \n\
378 if (!defined($hMTimeDeltas{$sPackageName}{'MTimeDelta'}) || $hMTimeDeltas{$sPackageName}{'MTimeDelta'} > $sMTimeDelta)\n\
379 {\n\
380 delete_package($sPackageName) if (defined($hMTimeDeltas{$sPackageName}{'MTimeDelta'}));\n\
381 local *FH;\n\
382 if (!open(FH, $sScript))\n\
383 {\n\
384 $@ = qq(script could not be opened ($!));\n\
385 return undef;\n\
386 }\n\
387 my $sScriptSource;\n\
388 while (my $sLine = <FH>)\n\
389 {\n\
390 last if ($sLine =~ /__(?:DATA|END)__/o);\n\
391 $sScriptSource .= $sLine;\n\
392 }\n\
393 close(FH);\n\
394 eval qq # Convert the script into a worker subroutine within its own unique package.\n\
395 {\n\
396 package $sPackageName;\n\
397 sub Worker\n\
398 {\n\
399 $sScriptSource;\n\
400 }\n\
401 };\n\
402 if ($@)\n\
403 {\n\
404 $@ =~ s/[\\t\\r\\n]+/ /g; $@ =~ s/\\s+/ /g; $@ =~ s/^\\s+//; $@ =~ s/\\s+$//;\n\
405 return undef;\n\
406 }\n\
407 $hMTimeDeltas{$sPackageName}{'MTimeDelta'} = $sMTimeDelta;\n\
408 }\n\
409 \n\
410 return $sPackageName;\n\
411 }\n\
412 \n\
413 1;\n\
414 ";
415 #endif
416
417 /*-
418 *********************************************************************
419 *
420 * Seed the random number generator, and generate a nonce.
421 *
422 *********************************************************************
423 */
424 TimeGetTimeValue(&psProperties->tvSRGEpoch);
425 iError = SeedRandom((unsigned long) psProperties->tvJobEpoch.tv_usec, (unsigned long) psProperties->tvSRGEpoch.tv_usec, acLocalError);
426 if (iError != ER_OK)
427 {
428 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
429 return ER;
430 }
431
432 psProperties->pcNonce = MakeNonce(acLocalError);
433 if (psProperties->pcNonce == NULL)
434 {
435 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
436 return ER;
437 }
438
439 #ifdef USE_EMBEDDED_PERL
440 if (RUN_MODE_IS_SET(FTIMES_DIGMADMAP, psProperties->iRunMode))
441 {
442 /*-
443 *********************************************************************
444 *
445 * Initialize the Perl interpreter.
446 *
447 *********************************************************************
448 */
449 PERL_SYS_INIT(&iArgumentCount, &ppcArgumentVector);
450 psProperties->psMyPerl = perl_alloc();
451 if (psProperties->psMyPerl == NULL)
452 {
453 snprintf(pcError, MESSAGE_SIZE, "%s: perl_alloc(): Unable to allocate a Perl interpreter.\n", acRoutine);
454 return ER;
455 }
456 PL_perl_destruct_level = 1; /* Setting this to 1 makes everything squeaky clean according to perlembed. */
457 perl_construct(psProperties->psMyPerl);
458 iPerlStatus = perl_parse(psProperties->psMyPerl, xs_init, iArgumentCount, ppcArgumentVector, NULL);
459 if (iPerlStatus != 0)
460 {
461 snprintf(pcError, MESSAGE_SIZE, "%s: perl_parse(): Failed to initialize the Perl interpreter.", acRoutine);
462 return ER;
463 }
464
465 /*-
466 *********************************************************************
467 *
468 * Initialize the script handler.
469 *
470 *********************************************************************
471 */
472 eval_sv(newSVpv(acScriptHandler, 0), G_KEEPERR);
473 if (SvTRUE(ERRSV))
474 {
475 snprintf(pcError, MESSAGE_SIZE, "%s: eval_sv(): Failed to initialize the Perl script handler (%s).", acRoutine, SvPV_nolen(ERRSV));
476 return ER;
477 }
478 }
479 #endif
480
481 #ifdef USE_EMBEDDED_PYTHON
482 if (RUN_MODE_IS_SET(FTIMES_DIGMADMAP, psProperties->iRunMode))
483 {
484 /*-
485 *********************************************************************
486 *
487 * Initialize the Python interpreter. Note that a failure inside this
488 * function pollutes stderr and ultimately leads to abort() by way of
489 * Py_FatalError(). It would be better if we could catch these errors
490 * and then decide how to handle them on our own.
491 *
492 *********************************************************************
493 */
494 Py_InitializeEx(0);
495
496 /*-
497 *********************************************************************
498 *
499 * Obtain references to the main module and its associated dictionary.
500 *
501 *********************************************************************
502 */
503 psProperties->psPythonMain = PyImport_AddModule("__main__");
504 if (psProperties->psPythonMain == NULL)
505 {
506 snprintf(pcError, MESSAGE_SIZE, "%s: PyImport_AddModule(): Failed to obtain a reference to the main module.", acRoutine);
507 return ER;
508 }
509 psProperties->psPyGlobals = PyModule_GetDict(psProperties->psPythonMain);
510 if (psProperties->psPyGlobals == NULL)
511 {
512 snprintf(pcError, MESSAGE_SIZE, "%s: PyModule_GetDict(): Failed to obtain a reference to the dictionary associated with the main module.", acRoutine);
513 return ER;
514 }
515 }
516 #endif
517
518 return ER_OK;
519 }
520
521
522 /*-
523 ***********************************************************************
524 *
525 * FTimesFreeProperties
526 *
527 ***********************************************************************
528 */
529 void
FTimesFreeProperties(FTIMES_PROPERTIES * psProperties)530 FTimesFreeProperties(FTIMES_PROPERTIES *psProperties)
531 {
532 if (psProperties != NULL)
533 {
534 DecodeFreeSnapshotContext(psProperties->psBaselineContext);
535 DecodeFreeSnapshotContext(psProperties->psSnapshotContext);
536 #ifdef USE_SSL
537 SslFreeProperties(psProperties->psSslProperties);
538 #endif
539 if (psProperties->pcNonce)
540 {
541 free(psProperties->pcNonce);
542 }
543 OptionsFreeOptionsContext(psProperties->psOptionsContext);
544 free(psProperties);
545 }
546 }
547
548
549 /*-
550 ***********************************************************************
551 *
552 * FTimesNewProperties
553 *
554 ***********************************************************************
555 */
556 FTIMES_PROPERTIES *
FTimesNewProperties(char * pcError)557 FTimesNewProperties(char *pcError)
558 {
559 const char acRoutine[] = "FTimesNewProperties()";
560 char acLocalError[MESSAGE_SIZE] = "";
561 char *pcValue = NULL;
562 FTIMES_PROPERTIES *psProperties;
563
564 /*
565 *********************************************************************
566 *
567 * Allocate and clear memory for the properties structure.
568 *
569 *********************************************************************
570 */
571 psProperties = (FTIMES_PROPERTIES *) calloc(sizeof(FTIMES_PROPERTIES), 1);
572 if (psProperties == NULL)
573 {
574 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
575 return NULL;
576 }
577
578 /*-
579 *********************************************************************
580 *
581 * Initialize variables that require a non-zero value.
582 *
583 *********************************************************************
584 */
585 TimeGetTimeValue(&psProperties->tvJobEpoch);
586 psProperties->dStartTime = (double) psProperties->tvJobEpoch.tv_sec + (double) psProperties->tvJobEpoch.tv_usec * 0.000001;
587 psProperties->tStartTime = TimeGetTime(psProperties->acStartDate, psProperties->acStartTime, psProperties->acStartZone, psProperties->acDateTime);
588 memcpy(psProperties->acRunDateTime, psProperties->acDateTime, FTIMES_TIME_SIZE);
589
590 /*
591 *********************************************************************
592 *
593 * Initialize function pointers.
594 *
595 *********************************************************************
596 */
597 psProperties->piDevelopMapOutput = DevelopNoOutput;
598
599 /*-
600 *********************************************************************
601 *
602 * Initialize LogLevel variable.
603 *
604 *********************************************************************
605 */
606 psProperties->iLogLevel = MESSAGE_LANDMARK;
607 MessageSetLogLevel(psProperties->iLogLevel);
608
609 /*-
610 *********************************************************************
611 *
612 * Initialize NewLine variable.
613 *
614 *********************************************************************
615 */
616 #ifdef WIN32
617 strncpy(psProperties->acNewLine, CRLF, NEWLINE_LENGTH);
618 #else
619 strncpy(psProperties->acNewLine, LF, NEWLINE_LENGTH);
620 #endif
621
622 /*-
623 *********************************************************************
624 *
625 * Initialize Pid variable.
626 *
627 *********************************************************************
628 */
629 snprintf(psProperties->acPid, FTIMES_PID_SIZE, "%d", (int) getpid());
630
631 /*-
632 *********************************************************************
633 *
634 * Initialize RunType variable.
635 *
636 *********************************************************************
637 */
638 strncpy(psProperties->acRunType, "baseline", RUNTYPE_BUFSIZE);
639
640 /*-
641 *********************************************************************
642 *
643 * Initialize EnableRecursion variable.
644 *
645 *********************************************************************
646 */
647 psProperties->bEnableRecursion = TRUE;
648
649 /*-
650 *********************************************************************
651 *
652 * Initialize Analyze*Size variables.
653 *
654 *********************************************************************
655 */
656 psProperties->iAnalyzeBlockSize = AnalyzeGetBlockSize();
657 psProperties->iAnalyzeCarrySize = AnalyzeGetCarrySize();
658 #ifdef USE_XMAGIC
659 psProperties->iAnalyzeStepSize = AnalyzeGetStepSize();
660 #endif
661
662 /*-
663 *********************************************************************
664 *
665 * Initialize baseline context.
666 *
667 *********************************************************************
668 */
669 psProperties->psBaselineContext = DecodeNewSnapshotContext(acLocalError);
670 if (psProperties->psBaselineContext == NULL)
671 {
672 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
673 FTimesFreeProperties(psProperties);
674 return NULL;
675 }
676
677 /*-
678 *********************************************************************
679 *
680 * Initialize snapshot context.
681 *
682 *********************************************************************
683 */
684 psProperties->psSnapshotContext = DecodeNewSnapshotContext(acLocalError);
685 if (psProperties->psSnapshotContext == NULL)
686 {
687 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
688 FTimesFreeProperties(psProperties);
689 return NULL;
690 }
691
692 #ifdef USE_SSL
693 /*-
694 *********************************************************************
695 *
696 * Initialize SSL properties.
697 *
698 *********************************************************************
699 */
700 psProperties->psSslProperties = SslNewProperties(acLocalError);
701 if (psProperties->psSslProperties == NULL)
702 {
703 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
704 FTimesFreeProperties(psProperties);
705 return NULL;
706 }
707 #endif
708
709 /*-
710 *********************************************************************
711 *
712 * Initialize TempDirectory variable.
713 *
714 *********************************************************************
715 */
716 #ifdef WIN32
717 pcValue = FTimesGetEnvValue("TEMP");
718 #else
719 pcValue = FTimesGetEnvValue("TMPDIR");
720 #endif
721 if (pcValue == NULL)
722 {
723 pcValue = FTimesGetEnvValue("TMP");
724 }
725 if (pcValue == NULL || strlen(pcValue) > sizeof(psProperties->acTempDirectory) - 1)
726 {
727 pcValue = FTIMES_TEMP_DIRECTORY;
728 }
729 strncpy(psProperties->acTempDirectory, pcValue, sizeof(psProperties->acTempDirectory));
730
731 /*-
732 *********************************************************************
733 *
734 * Initialize MemoryMapEnable variable -- it should be on by default.
735 * Next, check the environment to see if it should be disabled.
736 *
737 *********************************************************************
738 */
739 psProperties->iMemoryMapEnable = 1;
740 pcValue = FTimesGetEnvValue("FTIMES_MMAP_ENABLE");
741 if (pcValue != NULL && strlen(pcValue) == 1 && (pcValue[0] == '0' || pcValue[0] == 'N' || pcValue[0] == 'n'))
742 {
743 psProperties->iMemoryMapEnable = 0;
744 }
745
746 /*-
747 *********************************************************************
748 *
749 * Initialize the output's MD5 hash.
750 *
751 *********************************************************************
752 */
753 MD5Alpha(&psProperties->sOutFileHashContext);
754
755 return psProperties;
756 }
757
758
759 /*-
760 ***********************************************************************
761 *
762 * FTimesOptionHandler
763 *
764 ***********************************************************************
765 */
766 int
FTimesOptionHandler(OPTIONS_TABLE * psOption,char * pcValue,FTIMES_PROPERTIES * psProperties,char * pcError)767 FTimesOptionHandler(OPTIONS_TABLE *psOption, char *pcValue, FTIMES_PROPERTIES *psProperties, char *pcError)
768 {
769 const char acRoutine[] = "FTimesOptionHandler()";
770 char acLocalError[MESSAGE_SIZE] = "";
771 int iError = 0;
772 int iLength = 0;
773
774 iLength = (pcValue == NULL) ? 0 : strlen(pcValue);
775
776 switch (psOption->iId)
777 {
778 case OPT_LogLevel:
779 iError = SupportSetLogLevel(pcValue, &psProperties->iLogLevel, acLocalError);
780 if (iError != ER_OK)
781 {
782 snprintf(pcError, MESSAGE_SIZE, "%s: option=[%s]: Argument (%s) does not pass muster (%s).", acRoutine, psOption->atcFullName, pcValue, acLocalError);
783 return ER;
784 }
785 break;
786 case OPT_MagicFile:
787 if (iLength < 1 || iLength > FTIMES_MAX_PATH - 1)
788 {
789 snprintf(pcError, MESSAGE_SIZE, "%s: option=[%s]: Argument length must be in the range [1-%d].", acRoutine, psOption->atcFullName, FTIMES_MAX_PATH - 1);
790 return ER;
791 }
792 strncpy(psProperties->acMagicFileName, pcValue, FTIMES_MAX_PATH);
793 break;
794 case OPT_MemoryMapEnable:
795 if (strcasecmp(pcValue, "1") == 0 || strcasecmp(pcValue, "Y") == 0)
796 {
797 psProperties->iMemoryMapEnable = 1;
798 }
799 else if (strcasecmp(pcValue, "0") == 0 || strcasecmp(pcValue, "N") == 0)
800 {
801 psProperties->iMemoryMapEnable = 0;
802 }
803 else
804 {
805 snprintf(pcError, MESSAGE_SIZE, "%s: option=[%s]: Argument (%s) does not pass muster. Use one of \"Y\" or \"N\".", acRoutine, psOption->atcFullName, pcValue);
806 return ER;
807 }
808 break;
809 case OPT_NamesAreCaseInsensitive:
810 psProperties->psSnapshotContext->iNamesAreCaseInsensitive = 1;
811 psProperties->psBaselineContext->iNamesAreCaseInsensitive = 1;
812 break;
813 case OPT_StrictTesting:
814 psProperties->iTestLevel = FTIMES_TEST_STRICT;
815 break;
816 default:
817 snprintf(pcError, MESSAGE_SIZE, "%s: Invalid option ID (%d). This should not happen.", acRoutine, psOption->iId);
818 return ER;
819 break;
820 }
821
822 return ER_OK;
823 }
824
825
826 /*-
827 ***********************************************************************
828 *
829 * FTimesProcessArguments
830 *
831 ***********************************************************************
832 */
833 int
FTimesProcessArguments(FTIMES_PROPERTIES * psProperties,int iArgumentCount,char * ppcArgumentVector[],char * pcError)834 FTimesProcessArguments(FTIMES_PROPERTIES *psProperties, int iArgumentCount, char *ppcArgumentVector[], char *pcError)
835 {
836 const char acRoutine[] = "FTimesProcessArguments()";
837 char acLocalError[MESSAGE_SIZE] = "";
838 char *pcBaseline = NULL;
839 char *pcConfigFile = NULL;
840 char *pcMask = NULL;
841 char *pcMode = NULL;
842 char *pcSnapshot = NULL;
843 int iError = 0;
844 int iOperandCount = 0;
845 OPTIONS_CONTEXT *psOptionsContext = NULL;
846 static OPTIONS_TABLE asCfgtestOptions[] =
847 {
848 { OPT_StrictTesting, "-s", "--StrictTesting", 0, 0, 0, 0, FTimesOptionHandler },
849 };
850 static OPTIONS_TABLE asCompareOptions[] =
851 {
852 { OPT_LogLevel, "-l", "--LogLevel", 0, 0, 1, 0, FTimesOptionHandler },
853 { OPT_MemoryMapEnable, "", "--MemoryMapEnable", 0, 0, 1, 0, FTimesOptionHandler },
854 { OPT_NamesAreCaseInsensitive, "", "--NamesAreCaseInsensitive", 0, 0, 0, 0, FTimesOptionHandler },
855 };
856 static OPTIONS_TABLE asDecodeOptions[] =
857 {
858 { OPT_LogLevel, "-l", "--LogLevel", 0, 0, 1, 0, FTimesOptionHandler },
859 };
860 static OPTIONS_TABLE asDigOptions[] =
861 {
862 { OPT_LogLevel, "-l", "--LogLevel", 0, 0, 1, 0, FTimesOptionHandler },
863 };
864 static OPTIONS_TABLE asGetOptions[] =
865 {
866 { OPT_LogLevel, "-l", "--LogLevel", 0, 0, 1, 0, FTimesOptionHandler },
867 };
868 static OPTIONS_TABLE asMadOptions[] =
869 {
870 { OPT_LogLevel, "-l", "--LogLevel", 0, 0, 1, 0, FTimesOptionHandler },
871 { OPT_MagicFile, "", "--MagicFile", 0, 0, 1, 0, FTimesOptionHandler },
872 };
873 static OPTIONS_TABLE asMapOptions[] =
874 {
875 { OPT_LogLevel, "-l", "--LogLevel", 0, 0, 1, 0, FTimesOptionHandler },
876 { OPT_MagicFile, "", "--MagicFile", 0, 0, 1, 0, FTimesOptionHandler },
877 };
878
879 psProperties->pcProgram = ppcArgumentVector[0];
880
881 if (iArgumentCount < 2)
882 {
883 FTimesUsage();
884 }
885
886 /*-
887 *********************************************************************
888 *
889 * Initialize the options context.
890 *
891 *********************************************************************
892 */
893 psOptionsContext = OptionsNewOptionsContext(iArgumentCount, ppcArgumentVector, acLocalError);
894 if (psOptionsContext == NULL)
895 {
896 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
897 return ER;
898 }
899 psProperties->psOptionsContext = psOptionsContext;
900
901 /*-
902 *********************************************************************
903 *
904 * Determine the run mode.
905 *
906 *********************************************************************
907 */
908 psProperties->pcRunModeArgument = OptionsGetFirstArgument(psOptionsContext);
909 if (psProperties->pcRunModeArgument == NULL)
910 {
911 FTimesUsage();
912 }
913 else
914 {
915 if (strcmp(psProperties->pcRunModeArgument, "--cfgtest") == 0)
916 {
917 psProperties->iRunMode = FTIMES_CFGTEST;
918 //
919 OptionsSetOptions(psOptionsContext, asCfgtestOptions, (sizeof(asCfgtestOptions) / sizeof(asCfgtestOptions[0])));
920 //
921 psProperties->piRunModeFinalStage = PropertiesTestFile;
922 }
923 else if (strcmp(psProperties->pcRunModeArgument, "--compare") == 0)
924 {
925 psProperties->iRunMode = FTIMES_CMPMODE;
926 //
927 OptionsSetOptions(psOptionsContext, asCompareOptions, (sizeof(asCompareOptions) / sizeof(asCompareOptions[0])));
928 //
929 strcpy(psProperties->acDataType, FTIMES_CMPDATA);
930 //
931 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "CmpModeInitialize");
932 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Initialize;
933 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = CmpModeInitialize;
934 //
935 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "CmpModeCheckDependencies");
936 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_CheckDependencies;
937 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = CmpModeCheckDependencies;
938 //
939 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "CmpModeFinalize");
940 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Finalize;
941 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = CmpModeFinalize;
942 //
943 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "CmpModeWorkHorse");
944 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_WorkHorse;
945 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = CmpModeWorkHorse;
946 //
947 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "CmpModeFinishUp");
948 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_FinishUp;
949 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = CmpModeFinishUp;
950 //
951 psProperties->piRunModeFinalStage = CmpModeFinalStage;
952 }
953 else if (strcmp(psProperties->pcRunModeArgument, "--decode") == 0 || strcmp(psProperties->pcRunModeArgument, "--decoder") == 0)
954 {
955 psProperties->iRunMode = FTIMES_DECODER;
956 //
957 OptionsSetOptions(psOptionsContext, asDecodeOptions, (sizeof(asDecodeOptions) / sizeof(asDecodeOptions[0])));
958 //
959 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DecoderInitialize");
960 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Initialize;
961 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DecoderInitialize;
962 //
963 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DecoderCheckDependencies");
964 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_CheckDependencies;
965 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DecoderCheckDependencies;
966 //
967 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DecoderFinalize");
968 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Finalize;
969 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DecoderFinalize;
970 //
971 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DecoderWorkHorse");
972 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_WorkHorse;
973 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DecoderWorkHorse;
974 //
975 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DecoderFinishUp");
976 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_FinishUp;
977 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DecoderFinishUp;
978 //
979 psProperties->piRunModeFinalStage = DecoderFinalStage;
980 }
981 else if (strncmp(psProperties->pcRunModeArgument, "--dig", 5) == 0)
982 {
983 if (strcmp(psProperties->pcRunModeArgument, "--digauto") == 0)
984 {
985 psProperties->iRunMode = FTIMES_DIGAUTO;
986 }
987 else if (strcmp(psProperties->pcRunModeArgument, "--dig") == 0)
988 {
989 psProperties->iRunMode = FTIMES_DIGMODE;
990 }
991 else if (strcmp(psProperties->pcRunModeArgument, "--digfull") == 0)
992 {
993 psProperties->iRunMode = FTIMES_DIGMODE; /* Note that --digfull is maintained for backwards compatibility. */
994 }
995 else if (strcmp(psProperties->pcRunModeArgument, "--diglean") == 0)
996 {
997 psProperties->iRunMode = FTIMES_DIGMODE; /* Note that --diglean is maintained for backwards compatibility. */
998 }
999 else
1000 {
1001 FTimesUsage();
1002 }
1003 //
1004 OptionsSetOptions(psOptionsContext, asDigOptions, (sizeof(asDigOptions) / sizeof(asDigOptions[0])));
1005 //
1006 strcpy(psProperties->acDataType, FTIMES_DIGDATA);
1007 //
1008 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DigModeInitialize");
1009 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Initialize;
1010 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DigModeInitialize;
1011 //
1012 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DigModeCheckDependencies");
1013 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_CheckDependencies;
1014 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DigModeCheckDependencies;
1015 //
1016 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DigModeFinalize");
1017 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Finalize;
1018 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DigModeFinalize;
1019 //
1020 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DigModeWorkHorse");
1021 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_WorkHorse;
1022 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DigModeWorkHorse;
1023 //
1024 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "DigModeFinishUp");
1025 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_FinishUp;
1026 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = DigModeFinishUp;
1027 //
1028 psProperties->piRunModeFinalStage = DigModeFinalStage;
1029 }
1030 else if (strcmp(psProperties->pcRunModeArgument, "--get") == 0 || strcmp(psProperties->pcRunModeArgument, "--getmode") == 0)
1031 {
1032 psProperties->iRunMode = FTIMES_GETMODE;
1033 //
1034 OptionsSetOptions(psOptionsContext, asGetOptions, (sizeof(asGetOptions) / sizeof(asGetOptions[0])));
1035 //
1036 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "GetModeInitialize");
1037 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Initialize;
1038 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = GetModeInitialize;
1039 //
1040 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "GetModeCheckDependencies");
1041 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_CheckDependencies;
1042 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = GetModeCheckDependencies;
1043 //
1044 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "GetModeFinalize");
1045 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Finalize;
1046 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = GetModeFinalize;
1047 //
1048 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "GetModeWorkHorse");
1049 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_WorkHorse;
1050 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = GetModeWorkHorse;
1051 //
1052 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "GetModeFinishUp");
1053 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_FinishUp;
1054 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = GetModeFinishUp;
1055 //
1056 psProperties->piRunModeFinalStage = GetModeFinalStage;
1057 }
1058 else if (strcmp(psProperties->pcRunModeArgument, "--mad") == 0)
1059 {
1060 psProperties->iRunMode = FTIMES_MADMODE;
1061 //
1062 OptionsSetOptions(psOptionsContext, asMadOptions, (sizeof(asMadOptions) / sizeof(asMadOptions[0])));
1063 //
1064 strcpy(psProperties->acDataType, FTIMES_MADDATA);
1065 //
1066 strcpy(psProperties->acDigRecordPrefix, "dig|");
1067 strcpy(psProperties->acMapRecordPrefix, "map|");
1068 //
1069 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MadModeInitialize");
1070 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Initialize;
1071 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MadModeInitialize;
1072 //
1073 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MadModeCheckDependencies");
1074 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_CheckDependencies;
1075 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MadModeCheckDependencies;
1076 //
1077 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MadModeFinalize");
1078 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Finalize;
1079 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MadModeFinalize;
1080 //
1081 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MadModeWorkHorse");
1082 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_WorkHorse;
1083 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MadModeWorkHorse;
1084 //
1085 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MadModeFinishUp");
1086 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_FinishUp;
1087 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MadModeFinishUp;
1088 //
1089 psProperties->piRunModeFinalStage = MadModeFinalStage;
1090 }
1091 else if (strncmp(psProperties->pcRunModeArgument, "--map", 5) == 0)
1092 {
1093 if (strcmp(psProperties->pcRunModeArgument, "--mapauto") == 0)
1094 {
1095 psProperties->iRunMode = FTIMES_MAPAUTO;
1096 }
1097 else if (strcmp(psProperties->pcRunModeArgument, "--map") == 0)
1098 {
1099 psProperties->iRunMode = FTIMES_MAPMODE;
1100 }
1101 else if (strcmp(psProperties->pcRunModeArgument, "--mapfull") == 0)
1102 {
1103 psProperties->iRunMode = FTIMES_MAPMODE; /* Note that --mapfull is maintained for backwards compatibility. */
1104 }
1105 else if (strcmp(psProperties->pcRunModeArgument, "--maplean") == 0)
1106 {
1107 psProperties->iRunMode = FTIMES_MAPMODE; /* Note that --maplean is maintained for backwards compatibility. */
1108 }
1109 else
1110 {
1111 FTimesUsage();
1112 }
1113 //
1114 OptionsSetOptions(psOptionsContext, asMapOptions, (sizeof(asMapOptions) / sizeof(asMapOptions[0])));
1115 //
1116 strcpy(psProperties->acDataType, FTIMES_MAPDATA);
1117 //
1118 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MapModeInitialize");
1119 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Initialize;
1120 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MapModeInitialize;
1121 //
1122 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MapModeCheckDependencies");
1123 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_CheckDependencies;
1124 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MapModeCheckDependencies;
1125 //
1126 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MapModeFinalize");
1127 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_Finalize;
1128 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MapModeFinalize;
1129 //
1130 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MapModeWorkHorse");
1131 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_WorkHorse;
1132 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MapModeWorkHorse;
1133 //
1134 strcpy(psProperties->sRunModeStages[psProperties->iLastRunModeStage].acDescription, "MapModeFinishUp");
1135 psProperties->sRunModeStages[psProperties->iLastRunModeStage].iError = XER_FinishUp;
1136 psProperties->sRunModeStages[psProperties->iLastRunModeStage++].piRoutine = MapModeFinishUp;
1137 //
1138 psProperties->piRunModeFinalStage = MapModeFinalStage;
1139 }
1140 else if (strcmp(psProperties->pcRunModeArgument, "-v") == 0 || strcmp(psProperties->pcRunModeArgument, "--version") == 0)
1141 {
1142 FTimesVersion();
1143 }
1144 else
1145 {
1146 FTimesUsage();
1147 }
1148 }
1149 OptionsSetArgumentType(psOptionsContext, OPTIONS_ARGUMENT_TYPE_MODE);
1150
1151 /*-
1152 *********************************************************************
1153 *
1154 * Process options.
1155 *
1156 *********************************************************************
1157 */
1158 iError = OptionsProcessOptions(psOptionsContext, (void *) psProperties, acLocalError);
1159 switch (iError)
1160 {
1161 case OPTIONS_ER:
1162 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1163 return ER;
1164 break;
1165 case OPTIONS_OK:
1166 break;
1167 case OPTIONS_USAGE:
1168 default:
1169 FTimesUsage();
1170 break;
1171 }
1172
1173 /*-
1174 *********************************************************************
1175 *
1176 * Handle any special cases and/or remaining arguments.
1177 *
1178 *********************************************************************
1179 */
1180 iOperandCount = OptionsGetOperandCount(psOptionsContext);
1181 switch (psProperties->iRunMode)
1182 {
1183 case FTIMES_CFGTEST:
1184 if (iOperandCount != 2)
1185 {
1186 FTimesUsage();
1187 }
1188 pcConfigFile = OptionsGetFirstOperand(psOptionsContext);
1189 if (pcConfigFile == NULL)
1190 {
1191 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get config file argument.", acRoutine);
1192 return ER;
1193 }
1194 strncpy(psProperties->acConfigFile, pcConfigFile, FTIMES_MAX_PATH);
1195 pcMode = OptionsGetNextOperand(psOptionsContext);
1196 if (pcMode == NULL)
1197 {
1198 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get mode argument.", acRoutine);
1199 return ER;
1200 }
1201 if (strcasecmp(pcMode, "digauto") == 0)
1202 {
1203 psProperties->iTestRunMode = FTIMES_DIGAUTO;
1204 }
1205 else if
1206 (
1207 strcasecmp(pcMode, "dig") == 0 ||
1208 strcasecmp(pcMode, "digfull") == 0 ||
1209 strcasecmp(pcMode, "diglean") == 0
1210 )
1211 {
1212 psProperties->iTestRunMode = FTIMES_DIGMODE;
1213 }
1214 else if
1215 (
1216 strcasecmp(pcMode, "get") == 0 ||
1217 strcasecmp(pcMode, "getmode") == 0
1218 )
1219 {
1220 psProperties->iTestRunMode = FTIMES_GETMODE;
1221 }
1222 else if (strcasecmp(pcMode, "mad") == 0)
1223 {
1224 psProperties->iTestRunMode = FTIMES_MADMODE;
1225 }
1226 else if
1227 (
1228 strcasecmp(pcMode, "map") == 0 ||
1229 strcasecmp(pcMode, "mapfull") == 0 ||
1230 strcasecmp(pcMode, "maplean") == 0
1231 )
1232 {
1233 psProperties->iTestRunMode = FTIMES_MAPMODE;
1234 }
1235 else
1236 {
1237 snprintf(pcError, MESSAGE_SIZE, "%s: Mode = [%s]: Mode must be one of {dig|digauto|get|mad|map}.", acRoutine, pcMode);
1238 return ER;
1239 }
1240 break;
1241 case FTIMES_CMPMODE:
1242 if (iOperandCount != 3)
1243 {
1244 FTimesUsage();
1245 }
1246 pcMask = OptionsGetFirstOperand(psOptionsContext);
1247 if (pcMask == NULL)
1248 {
1249 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get mask argument.", acRoutine);
1250 return ER;
1251 }
1252 psProperties->psFieldMask = MaskParseMask(pcMask, MASK_RUNMODE_TYPE_CMP, acLocalError);
1253 if (psProperties->psFieldMask == NULL)
1254 {
1255 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1256 return ER;
1257 }
1258 pcBaseline = OptionsGetNextOperand(psOptionsContext);
1259 if (pcBaseline == NULL)
1260 {
1261 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get mask argument.", acRoutine);
1262 return ER;
1263 }
1264 psProperties->psBaselineContext->pcFile = pcBaseline;
1265 pcSnapshot = OptionsGetNextOperand(psOptionsContext);
1266 if (pcSnapshot == NULL)
1267 {
1268 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get mask argument.", acRoutine);
1269 return ER;
1270 }
1271 psProperties->psSnapshotContext->pcFile = pcSnapshot;
1272 break;
1273 case FTIMES_DECODER:
1274 if (iOperandCount != 1)
1275 {
1276 FTimesUsage();
1277 }
1278 pcSnapshot = OptionsGetNextOperand(psOptionsContext);
1279 if (pcSnapshot == NULL)
1280 {
1281 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get mask argument.", acRoutine);
1282 return ER;
1283 }
1284 psProperties->psSnapshotContext->pcFile = pcSnapshot;
1285 break;
1286 case FTIMES_DIGAUTO:
1287 case FTIMES_DIGMODE:
1288 case FTIMES_MADMODE:
1289 case FTIMES_MAPMODE:
1290 if (iOperandCount < 1)
1291 {
1292 FTimesUsage();
1293 }
1294 pcConfigFile = OptionsGetFirstOperand(psOptionsContext);
1295 if (pcConfigFile == NULL)
1296 {
1297 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get config file argument.", acRoutine);
1298 return ER;
1299 }
1300 if (strcmp(pcConfigFile, "-") == 0)
1301 {
1302 strcpy(psProperties->acConfigFile, "-");
1303 }
1304 else
1305 {
1306 iError = SupportExpandPath(pcConfigFile, psProperties->acConfigFile, FTIMES_MAX_PATH, 1, acLocalError);
1307 if (iError != ER_OK)
1308 {
1309 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1310 return ER;
1311 }
1312 iError = SupportAddToList(psProperties->acConfigFile, &psProperties->psExcludeList, "Exclude", acLocalError);
1313 if (iError != ER_OK)
1314 {
1315 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1316 return ER;
1317 }
1318 }
1319 /* Note: Any remaining operands will be treated as includes. */
1320 break;
1321 case FTIMES_GETMODE:
1322 if (iOperandCount != 1)
1323 {
1324 FTimesUsage();
1325 }
1326 pcConfigFile = OptionsGetFirstOperand(psOptionsContext);
1327 if (pcConfigFile == NULL)
1328 {
1329 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get config file argument.", acRoutine);
1330 return ER;
1331 }
1332 strncpy(psProperties->acConfigFile, pcConfigFile, FTIMES_MAX_PATH);
1333 break;
1334 case FTIMES_MAPAUTO:
1335 if (iOperandCount < 1)
1336 {
1337 FTimesUsage();
1338 }
1339 pcMask = OptionsGetFirstOperand(psOptionsContext);
1340 if (pcMask == NULL)
1341 {
1342 snprintf(pcError, MESSAGE_SIZE, "%s: Unable to get mask argument.", acRoutine);
1343 return ER;
1344 }
1345 psProperties->psFieldMask = MaskParseMask(pcMask, MASK_RUNMODE_TYPE_MAP, acLocalError);
1346 if (psProperties->psFieldMask == NULL)
1347 {
1348 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1349 return ER;
1350 }
1351 /* Note: Any remaining operands will be treated as includes. */
1352 break;
1353 default:
1354 FTimesUsage();
1355 break;
1356 }
1357
1358 /*-
1359 *********************************************************************
1360 *
1361 * If any required arguments are missing, it's an error.
1362 *
1363 *********************************************************************
1364 */
1365 if (OptionsHaveRequiredOptions(psOptionsContext) == 0)
1366 {
1367 FTimesUsage();
1368 }
1369
1370 return ER_OK;
1371 }
1372
1373
1374 /*-
1375 ***********************************************************************
1376 *
1377 * FTimesStagesLoop
1378 *
1379 ***********************************************************************
1380 */
1381 int
FTimesStagesLoop(FTIMES_PROPERTIES * psProperties,char * pcError)1382 FTimesStagesLoop(FTIMES_PROPERTIES *psProperties, char *pcError)
1383 {
1384 const char acRoutine[] = "FTimesStagesLoop()";
1385 char acLocalError[MESSAGE_SIZE] = "";
1386 char acMessage[MESSAGE_SIZE];
1387 int i;
1388 int iError;
1389
1390 /*-
1391 *******************************************************************
1392 *
1393 * Display some basic information.
1394 *
1395 *******************************************************************
1396 */
1397 snprintf(acMessage, MESSAGE_SIZE, "Program=%s %s", VersionGetVersion(), psProperties->pcRunModeArgument);
1398 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1399
1400 snprintf(acMessage, MESSAGE_SIZE, "SystemOS=%s", SupportGetSystemOS());
1401 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1402
1403 snprintf(acMessage, MESSAGE_SIZE, "Hostname=%s", SupportGetHostname());
1404 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1405
1406 if (psProperties->tStartTime == ER)
1407 {
1408 snprintf(acMessage, MESSAGE_SIZE, "JobEpoch=NA");
1409 }
1410 else
1411 {
1412 snprintf(acMessage, MESSAGE_SIZE, "JobEpoch=%s %s %s", psProperties->acStartDate, psProperties->acStartTime, psProperties->acStartZone);
1413 }
1414 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1415
1416 snprintf(acMessage, MESSAGE_SIZE, "JobPid=%s", psProperties->acPid);
1417 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1418
1419 #ifdef UNIX
1420 snprintf(acMessage, MESSAGE_SIZE, "JobUid=%d", (int) getuid());
1421 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1422 #endif
1423
1424 snprintf(acMessage, MESSAGE_SIZE, "LogLevel=%d", psProperties->iLogLevel);
1425 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_INFORMATION, MESSAGE_PROPERTY_STRING, acMessage);
1426
1427 /*-
1428 *******************************************************************
1429 *
1430 * Loop over the RunMode stages.
1431 *
1432 *******************************************************************
1433 */
1434 for (i = 0; i < psProperties->iLastRunModeStage; i++)
1435 {
1436 if (psProperties->sRunModeStages[i].piRoutine != NULL)
1437 {
1438 snprintf(acMessage, MESSAGE_SIZE, "Stage%d=%s", i + 1, psProperties->sRunModeStages[i].acDescription);
1439 MessageHandler(MESSAGE_QUEUE_IT, MESSAGE_LANDMARK, MESSAGE_LANDMARK_STRING, acMessage);
1440 iError = psProperties->sRunModeStages[i].piRoutine(psProperties, acLocalError);
1441 if (iError != ER_OK)
1442 {
1443 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1444 return psProperties->sRunModeStages[i].iError;
1445 }
1446 }
1447 }
1448
1449 MessageHandler(MESSAGE_FLUSH_IT, MESSAGE_ALWAYSON, NULL, NULL);
1450
1451 return ER_OK;
1452 }
1453
1454
1455 /*-
1456 ***********************************************************************
1457 *
1458 * FTimesFinalStage
1459 *
1460 ***********************************************************************
1461 */
1462 int
FTimesFinalStage(FTIMES_PROPERTIES * psProperties,char * pcError)1463 FTimesFinalStage(FTIMES_PROPERTIES *psProperties, char *pcError)
1464 {
1465 const char acRoutine[] = "FTimesFinalStage()";
1466 char acLocalError[MESSAGE_SIZE] = "";
1467 int iError;
1468
1469 /*-
1470 *********************************************************************
1471 *
1472 * Flush the Message Handler, and close the LogFile stream.
1473 *
1474 *********************************************************************
1475 */
1476 if (psProperties->pFileLog && psProperties->pFileLog != stderr)
1477 {
1478 MessageHandler(MESSAGE_FLUSH_IT, MESSAGE_INFORMATION, NULL, NULL);
1479 fclose(psProperties->pFileLog);
1480 psProperties->pFileLog = NULL;
1481 }
1482
1483 /*-
1484 *********************************************************************
1485 *
1486 * Invoke the RunMode specific routine.
1487 *
1488 *********************************************************************
1489 */
1490 if (psProperties->piRunModeFinalStage)
1491 {
1492 iError = psProperties->piRunModeFinalStage(psProperties, acLocalError);
1493 if (iError != ER_OK)
1494 {
1495 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1496 return ER;
1497 }
1498 }
1499
1500 #ifdef WINNT
1501 /*-
1502 *********************************************************************
1503 *
1504 * Release any library handles.
1505 *
1506 *********************************************************************
1507 */
1508 if (NtdllHandle)
1509 {
1510 FreeLibrary(NtdllHandle);
1511 }
1512 #endif
1513
1514 #ifdef USE_EMBEDDED_PERL
1515 /*-
1516 *********************************************************************
1517 *
1518 * Release the Perl interpreter.
1519 *
1520 *********************************************************************
1521 */
1522 if (psProperties->psMyPerl != NULL)
1523 {
1524 PL_perl_destruct_level = 1; /* This must be set to 1 since perl_construct() reset it to 0 according to perlembed. */
1525 perl_destruct(psProperties->psMyPerl);
1526 perl_free(psProperties->psMyPerl);
1527 PERL_SYS_TERM();
1528 }
1529 #endif
1530
1531 #ifdef USE_EMBEDDED_PYTHON
1532 /*-
1533 *********************************************************************
1534 *
1535 * Release the Python interpreter.
1536 *
1537 *********************************************************************
1538 */
1539 Py_XDECREF(psProperties->psPyGlobals);
1540 Py_Finalize();
1541 #endif
1542
1543 return ER_OK;
1544 }
1545
1546
1547 /*-
1548 ***********************************************************************
1549 *
1550 * FTimesUsage
1551 *
1552 ***********************************************************************
1553 */
1554 void
FTimesUsage(void)1555 FTimesUsage(void)
1556 {
1557 fprintf(stderr, "\n");
1558 fprintf(stderr, "Usage: ftimes --cfgtest file mode [-s]\n");
1559 fprintf(stderr, " ftimes --compare mask baseline snapshot [-l {0-6}]\n");
1560 fprintf(stderr, " ftimes --decode snapshot [-l {0-6}]\n");
1561 fprintf(stderr, " ftimes --dig file [-l {0-6}] [target [...]]\n");
1562 fprintf(stderr, " ftimes --digauto file [-l {0-6}] [target [...]]\n");
1563 fprintf(stderr, " ftimes --get file [-l {0-6}]\n");
1564 fprintf(stderr, " ftimes --mad file [-l {0-6}] [target [...]]\n");
1565 fprintf(stderr, " ftimes --map file [-l {0-6}] [target [...]]\n");
1566 fprintf(stderr, " ftimes --mapauto mask [-l {0-6}] [target [...]]\n");
1567 fprintf(stderr, " ftimes {-v|--version}\n");
1568 fprintf(stderr, "\n");
1569 exit(XER_Usage);
1570 }
1571
1572
1573 /*-
1574 ***********************************************************************
1575 *
1576 * FTimesVersion
1577 *
1578 ***********************************************************************
1579 */
1580 void
FTimesVersion(void)1581 FTimesVersion(void)
1582 {
1583 fprintf(stdout, "%s\n", VersionGetVersion());
1584 exit(XER_OK);
1585 }
1586
1587
1588 /*-
1589 ***********************************************************************
1590 *
1591 * FTimesSetPropertiesReference
1592 *
1593 ***********************************************************************
1594 */
1595 void
FTimesSetPropertiesReference(FTIMES_PROPERTIES * psProperties)1596 FTimesSetPropertiesReference(FTIMES_PROPERTIES *psProperties)
1597 {
1598 gpsProperties = psProperties;
1599 DigSetPropertiesReference(psProperties);
1600 }
1601
1602
1603 /*-
1604 ***********************************************************************
1605 *
1606 * FTimesGetEnvValue
1607 *
1608 ***********************************************************************
1609 */
1610 char *
FTimesGetEnvValue(char * pcName)1611 FTimesGetEnvValue(char *pcName)
1612 {
1613 #ifdef WIN32
1614 char *pcValue = NULL;
1615 DWORD dwCount = 0;
1616
1617 #define FTIMES_MAX_ENV_SIZE 32767 /* Source = MSDN documentation for GetEnvironmentVariable() */
1618 pcValue = calloc(FTIMES_MAX_ENV_SIZE, 1);
1619 if (pcValue == NULL)
1620 {
1621 return NULL;
1622 }
1623 dwCount = GetEnvironmentVariable(TEXT(pcName), pcValue, FTIMES_MAX_ENV_SIZE);
1624 return (dwCount == 0 || dwCount > FTIMES_MAX_ENV_SIZE) ? NULL : pcValue;
1625 #else
1626 return getenv(pcName);
1627 #endif
1628 }
1629
1630
1631 /*-
1632 ***********************************************************************
1633 *
1634 * FTimesGetPropertiesReference
1635 *
1636 ***********************************************************************
1637 */
1638 FTIMES_PROPERTIES *
FTimesGetPropertiesReference(void)1639 FTimesGetPropertiesReference(void)
1640 {
1641 return gpsProperties;
1642 }
1643
1644
1645 /*-
1646 ***********************************************************************
1647 *
1648 * FTimesEraseFiles
1649 *
1650 ***********************************************************************
1651 */
1652 void
FTimesEraseFiles(FTIMES_PROPERTIES * psProperties,char * pcError)1653 FTimesEraseFiles(FTIMES_PROPERTIES *psProperties, char *pcError)
1654 {
1655 const char acRoutine[] = "FTimesEraseFiles()";
1656 char acLocalError[MESSAGE_SIZE] = "";
1657 int iError;
1658
1659 iError = SupportEraseFile(psProperties->acLogFileName, acLocalError);
1660 if (iError != ER_OK)
1661 {
1662 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s]: %s", acRoutine, psProperties->acLogFileName, acLocalError);
1663 ErrorHandler(ER_Warning, pcError, ERROR_WARNING);
1664 }
1665 iError = SupportEraseFile(psProperties->acOutFileName, acLocalError);
1666 if (iError != ER_OK)
1667 {
1668 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s]: %s", acRoutine, psProperties->acOutFileName, acLocalError);
1669 ErrorHandler(ER_Warning, pcError, ERROR_WARNING);
1670 }
1671 }
1672
1673
1674 /*-
1675 ***********************************************************************
1676 *
1677 * MakeNonce
1678 *
1679 ***********************************************************************
1680 */
1681 char *
MakeNonce(char * pcError)1682 MakeNonce(char *pcError)
1683 {
1684 const char acRoutine[] = "MakeNonce()";
1685 char *pcNonce = NULL;
1686 unsigned char a = 0;
1687 unsigned char b = 0;
1688 unsigned char c = 0;
1689 unsigned char d = 0;
1690 long lValue = 0;
1691
1692 #ifdef WIN32
1693 lValue = (GetTickCount() << 16) | rand();
1694 #else
1695 lValue = random();
1696 #endif
1697 a = (unsigned char) ((lValue >> 24) & 0xff);
1698 b = (unsigned char) ((lValue >> 16) & 0xff);
1699 c = (unsigned char) ((lValue >> 8) & 0xff);
1700 d = (unsigned char) ((lValue >> 0) & 0xff);
1701 pcNonce = calloc(FTIMES_NONCE_SIZE, 1);
1702 if (pcNonce == NULL)
1703 {
1704 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
1705 return NULL;
1706 }
1707 snprintf(pcNonce, FTIMES_NONCE_SIZE, "%02x%02x%02x%02x", a, b, c, d);
1708 return pcNonce;
1709 }
1710
1711
1712 /*-
1713 ***********************************************************************
1714 *
1715 * SeedRandom
1716 *
1717 ***********************************************************************
1718 */
1719 int
SeedRandom(unsigned long ulTime1,unsigned long ulTime2,char * pcError)1720 SeedRandom(unsigned long ulTime1, unsigned long ulTime2, char *pcError)
1721 {
1722 const char acRoutine[] = "SeedRandom()";
1723
1724 if (ulTime1 == (unsigned long) ~0 || ulTime2 == (unsigned long) ~0)
1725 {
1726 snprintf(pcError, MESSAGE_SIZE, "%s: Seed values are blatantly abnormal!: Time1 = [%08lx], Time2 = [%08lx]", acRoutine, ulTime1, ulTime2);
1727 return ER;
1728 }
1729
1730 #ifdef WIN32
1731 srand((unsigned long) (0xE97482AD ^ ((ulTime1 << 16) | (ulTime1 >> 16)) ^ ulTime2 ^ getpid() ^ GetTickCount()));
1732 #else
1733 srandom((unsigned long) (0xE97482AD ^ ((ulTime1 << 16) | (ulTime1 >> 16)) ^ ulTime2 ^ getpid()));
1734 #endif
1735 return ER_OK;
1736 }
1737
1738
1739 #ifdef USE_SSL
1740 /*-
1741 ***********************************************************************
1742 *
1743 * SSLCheckDependencies
1744 *
1745 ***********************************************************************
1746 */
1747 int
SSLCheckDependencies(SSL_PROPERTIES * psProperties,char * pcError)1748 SSLCheckDependencies(SSL_PROPERTIES *psProperties, char *pcError)
1749 {
1750 const char acRoutine[] = "SSLCheckDependencies()";
1751
1752 if (psProperties->iUseCertificate)
1753 {
1754 if (psProperties->pcPublicCertFile == NULL || psProperties->pcPublicCertFile[0] == 0)
1755 {
1756 snprintf(pcError, MESSAGE_SIZE, "%s: Missing SSLPublicCertFile.", acRoutine);
1757 return ER;
1758 }
1759
1760 if (psProperties->pcPrivateKeyFile == NULL || psProperties->pcPrivateKeyFile[0] == 0)
1761 {
1762 snprintf(pcError, MESSAGE_SIZE, "%s: Missing SSLPrivateKeyFile.", acRoutine);
1763 return ER;
1764 }
1765 }
1766
1767 if (psProperties->iVerifyPeerCert)
1768 {
1769 if (psProperties->pcBundledCAsFile == NULL || psProperties->pcBundledCAsFile[0] == 0)
1770 {
1771 snprintf(pcError, MESSAGE_SIZE, "%s: Missing SSLBundledCAsFile.", acRoutine);
1772 return ER;
1773 }
1774
1775 if (psProperties->pcExpectedPeerCN == NULL || psProperties->pcExpectedPeerCN[0] == 0)
1776 {
1777 snprintf(pcError, MESSAGE_SIZE, "%s: Missing SSLExpectedPeerCN.", acRoutine);
1778 return ER;
1779 }
1780 }
1781
1782 return ER_OK;
1783 }
1784 #endif
1785