Gathered Symantec Details by command

#!/bin/sh # File Name: GatherSymantecInfo.command Version=4.0.8 # Author: Corey Swertfager, Symantec Corporation # Created: 05/07/2009 # Modified: 06/27/2019 # # Usage: See ShowHelp() function. # # Summary: See ShowHelp() function. # # History: 1.00 - Created. # 1.01 - Now makes tools executable before running them. # Added table of contents to report. # Added SymSharedSettingsd -V output. # Added listing of files in Symantec's support folders. # Added display of the last 300 lines in system.log. # Added display of the last 20 lines in: # /Library/Application Support/Symantec/Daemon/error.log # Added date and time to beginning of report. # Added zip program to SupportDir. # Report is now zipped. # 1.02 - Added /private/tmp and /private/var/tmp file listings. # Added display of Symantec Info.plist contents and removed # "Subscription plug-ins" section, since the plug-ins' # plists are part of that display. # Added AllFiles.txt to SupportDir. # 1.03 - Added listing of links expected in /. # Added contents of CrashReporter logs with file names that # begin with Norton or Sym. # Added contents of /Library/LaunchAgents/com.symantec.*. # Added contents of loginwindow.plist files. # Increased number of system.log lines to display to 600. # Added output of year in ls listings of tmp directories. # Added -f option to various ls -l listings. # Now shows only indented entries when showing contents of # any plist file. # Removed redundant blank lines from most report sections. # Added the following to "AllFiles.txt": # /Library/LaunchAgents/com.symantec.* # /Library/LaunchAgents/com.Symantec.* # /Library/Receipts/SMC.pkg # /Library/Receipts/SNAC.pkg # /Library/Receipts/Symantec Endpoint Protection.pkg # /Library/Receipts/SymantecSAQuickMenu.pkg # /Library/Services # /Library/StartupItems/SMC # /usr/lib/libsymsea.1.0.0.dylib # /usr/lib/libsymsea.dylib # 1.04 - Added John Hansen's PrintShutDownTimes program. # Revised OS version display for OS 10.6 compatibility. # Redirected system_profiler errors. # Replaced ShowNortonAppInfo.command with version 2.05. # Report text file is no longer deleted. # 1.05 - Replaced ShowRegistryInfo with version 1.02. # 1.06 - Purged PrintShutDownTimes entries created by this program # from system.log output. # Removed ShowContents function. # Added the following to "AllFiles.txt": # /Library/ScriptingAdditions/SymWebKitUtils.osax # /Library/ScriptingAdditions/SymWebKitUtilsSL.osax # /Library/StartupItems/SymWebKitUtilsOSFix # Updated help. # 1.07 - Added tab support for files listed in for "AllFiles.txt". # Replaced GetIPSsignaturesDate.command with version 1.05. # 1.08 - Replaced ShowNortonAppInfo.command with version 2.06. # 1.09 - ScriptPath definition added for better script linking. # 1.10 - Added keychain location listing. # 1.11 - Reconfigured tr command error output. # 1.12 - Replaced ShowNortonAppInfo.command with version 2.07. # Added content display of plists matching # /Library/LaunchDaemons/com.norton.*. # Added the following to "AllFiles.txt": # /Library/LaunchDaemons/com.Norton.* # /Library/LaunchDaemons/com.norton.* # /private/var/log/nortondns.log # 1.13 - Replaced DefineCurrentUserAndDesktop with DefineCurrentUserDesktopAndOS. # 1.14 - Revised Symantec process output to include more info by passing aux # to ps instead of -wwax. # Added listing: "All processes in memory". # 1.15 - Added Symantec Endpoint Protection debug log and Sy*.xml files. # 1.16 - Contents of all Info.plist files in support folders are now shown # instead of just those within Contents folders. # 1.17 - All crontab entries and launchd item contents are now shown. # CatFilesInList function now converts plist files to xml and # reports an error if the plist cannot be converted. # 1.18 - Added 32-bit/64-bit labeling to OS version info. # 1.19 - Added -ww to ps calls to include full command calls. # 1.20 - Added display the last 1600 lines of /var/log/install.log. # Added -u option to show unlimited number of lines in logs. # Added prompt to show all lines in logs. # 1.21 - Replaced ShowNortonAppInfo.command with version 3.0.0. # Removed ShowRegistryInfo program. # Add file option. # 1.22 - Replaced ShowNortonAppInfo.command with version 3.0.1. # 1.23 - Modified for case-sensitive volume compatibility. # Replaced ShowFullFilePath function with version 1.0.2. # Replaced ShowNortonAppInfo.command with version 3.0.2. # 1.24 - Added display of LiveUpdate 6 log. # Added IRSpecial to show LiveUpdate 5 subscriptions # when IRTool is not installed. # Added display of /Library/Logs/SymantecTestPatchers.log. # Replaced ShowNortonAppInfo.command with version 3.0.3. # Added -a to ShowNortonAppInfo.command call. # Added fat version of GetFileInfo. # LiveUpdate 3-4 subscriptions are now only checked on PPC # or when Mac OS version is less than 10.5. # 1.25 - Replaced GetDefsDate.command with version 1.08 to display # NAV 12-style engine and hub folders. # 1.26 - Replaced ShowNortonAppInfo.command with version 3.0.4. # 1.27 - Replaced ShowNortonAppInfo.command with version 3.0.5. # 1.28 - Replaced YorN function with version 1.0.1. # 1.29 - Replaced GetDefsDate.command with version 1.09 to display # build number of virus defs. # 1.30 - Replaced ShowNortonAppInfo.command with version 3.0.6. # 1.31 - Added content of LiveUpdate CrashReporter logs and logs in: # /Library/Application Support/Symantec/Licensing # Replaced ShowNortonAppInfo.command with version 3.0.7. # 1.32 - 08/23/2011: # Replaced ShowNortonAppInfo.command with version 3.0.8. # 1.33 - 08/26/2011: # Added content of xml files in: # /Library/Application Support/Symantec/ErrorReporting/Submissions # 1.34 - 09/13/2011: # Replaced ShowNortonAppInfo.command with version 3.0.9. # 1.35 - 10/07/2011: # Added to "AllFiles.txt": # /Library/Application Support/nav_postuninstall.rb # /Library/Application Support/nsm_postuninstall.rb # /Library/Application Support/o2spy.log # /Library/PrivateFrameworks/PlausibleDatabase.framework # /Library/PrivateFrameworks/SymOxygen.framework # 1.36 - 12/07/2011: # Added to "AllFiles.txt": # /Library/PrivilegedHelperTools/NATRemoteLock.app # /usr/lib/libwpsapi.dylib # 1.37 - 12/14/2011: # Added to "AllFiles.txt": # /private/var/db/NATSqlDatabase.db # 2.0.0 - 02/05/2012: # * Added VerifySignedFiles.command 1.28 + Paths-MasterList.txt. # * Added -a option to append report to file. # * Added -s option to bypass running of VerifySignedFiles. # * Added -z option to created zip file in location other than Desktop. # * Files passed that do not follow -a or -z are now added to the # report zip archive instead of having the report appended to. # * The report text file is no longer saved to Desktop unless -o is # passed and no output file is passed. # * Removed prompt for subscription key. # * Added liveupdate.log.zip to SymantecInfo.zip. # * Replaced ShowNortonAppInfo.command with version 3.0.10. # * Removed SupportFiles/ppc folder. # 2.0.1 - 02/09/2012: # * Added kernel.log to SymantecInfo.zip. # * Sorted list of additional files added to zip archive. # 2.0.2 - 03/02/2012: # * Added navmanout to SupportFiles. # * Added NAV 12 virus definitions manifest output via navmanout. # 2.0.3 - 03/30/2012: # Added to "AllFiles.txt": # /Library/Application Support/nav_uninstalldashboard* # /Library/Application Support/nis_postuninstall.rb # /Library/Application Support/nis_postuninstall.sh # /Library/InputManagers/SymWebKitUtils # /Library/StartupItems/SymQuickMenuOSFix # /private/var/db/receipts/com.Symantec* # /private/var/db/receipts/com.symantec* # 2.0.4 - 05/23/2012: # Replaced ShowNortonAppInfo.command with version 3.0.11. # 2.0.5 - 07/03/2012 - Corey Swertfager: # * Replaced YorN function with version 1.0.2. # * Added VerifySignedFiles.command 1.28 + Paths-MasterList.txt. # 2.0.6 - 07/06/2012 - Corey Swertfager: # Replaced ShowNortonAppInfo.command with version 3.0.12. # 2.0.7 - 07/17/2012 - Corey Swertfager: # Replaced VerifySignedFiles.command with version 1.30. # 2.0.8 - 08/03/2012 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 1.31. # * Added to "AllFiles.txt": # /Library/Frameworks/mach_inject_bundle.framework # /Library/Frameworks/mach_inject_bundle.framework/Versions/Current/Resources/mach_inject_bundle_stub.bundle # /Library/Application Support/Symantec/Mexico/FinderPlugin.bundle # 2.0.9 - 10/16/2012 - Corey Swertfager: # * Replaced ShowNortonAppInfo.command with version 3.0.13. # * Replaced VerifySignedFiles.command with version 1.32. # * Added to "AllFiles.txt": # /Library/Internet Plug-Ins/NortonInternetSecurityBF.plugin # 2.0.10 - 03/12/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 1.33. # * Added watermark ID. # 2.0.11 - 03/14/2013 - Corey Swertfager: # * Revised plist and xml content sifting to avoid missing data. # 2.0.12 - 04/10/2013 - Corey Swertfager: # * Moved full VerifySignedFiles folder into SupportFiles directory. # * Removed Paths-MasterList.txt and VerifySignedFiles.command from # SupportFiles directory. # 2.0.13 - 05/10/2013 - Corey Swertfager: # * Now shows contents of LUX logs for Norton Zone: # /var/log/luxtool.log # /var/log/luxtool.log.1 # 2.0.14 - 05/24/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 1.34. # 2.1.0 - 06/28/2013 - Corey Swertfager: # * ProcessArguments 1.0.1 is now used to process arguments to allow # options to be combined in one argument that begins with a single # hyphen (e.g., passing -ab to script would be equivalent to passing # -a and -b separately; --ab would be treated as a single option). # * Replaced "sort -fu" with "sort -f | uniq". # 2.1.1 - 06/30/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.0. # * Added to "AllFiles.txt": # /System/Library/Extensions/NortonForMac.kext # /usr/bin/nortonscanner # /usr/bin/nortonsettings # 2.1.2 - 07/10/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.1. # 2.1.3 - 07/14/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.2. # 2.1.4 - 07/17/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.3. # 3.0.0 - 07/19/2013 - Corey Swertfager: # * Updated version to make sure tools updater finds this program. # 3.0.1 - 08/16/2013 - Corey Swertfager: # * Added NIS 6 LUX logs if LoggingTool.command exists. # * Replaced ShowNortonAppInfo.command with version 3.0.14. # 3.0.2 - 09/05/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.4. # 3.0.3 - 09/05/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.5. # 3.0.4 - 09/11/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.6. # 3.0.5 - 09/24/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.7. # * Added to "AllFiles.txt" (also used by CopyFilesIntoFolder): # /Library/Extensions/FileSecurity* # /Library/Extensions/Sym* # /private/etc/symantec # /usr/local/lib/libcx_lib.so # /usr/local/lib/liblux.so.* # /usr/local/lib/libnlucallback.dylib # /var/log/lux.log* # /var/log/du.log* # /var/log/dulux.log* # /var/log/lut.log* # /var/log/mexd.log* # /var/log/microdef.log* # 3.0.6 - 09/25/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.8. # 3.0.7 - 11/12/2013 - Corey Swertfager: # * Replaced GetDefsDate.command with version 2.0.0. # * Replaced GetIPSsignaturesDate.command with version 2.0.0. # * Replaced GetWCIDdefsDate.command with version 2.0.0. # * Added support for NIS 6 in GetDefsDate.command, # GetIPSsignaturesDate.command and GetWCIDdefsDate.command. # 3.0.8 - 12/03/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.9. # * Lines that begin with "<" are no longer filtered out when # CatFilesInList function shows contents of xml files. # * Now shows contents of SEP debug logs: # /Library/Application Support/Symantec/SMC/debug/*.log # * Added Serdef.dat to SymantecInfo.zip. # 3.0.9 - 12/05/2013 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.10. # 3.0.10 - 01/16/2014 - Corey Swertfager: # * Replaced GetDefsDate.command with version 2.0.1. # * Replaced ShowNortonAppInfo.command with version 3.0.15. # * Replaced VerifySignedFiles.command with version 2.0.11. # 3.0.11 - 01/28/2014 - Corey Swertfager: # * Now shows contents of NIS 6 LiveUpdate logs: # /Library/Application Support/Symantec/Silo/NFM/LiveUpdate/Logs/devlux.log # /Library/Application Support/Symantec/Silo/NFM/LiveUpdate/Logs/LiveUpdateLog # /Library/Application Support/Symantec/Silo/NFM/LiveUpdate/Logs/lux.log # /var/log/du.log # * Now adds rollover NIS 6 LUX text log to zip archive: # /Library/Application Support/Symantec/Silo/NFM/LiveUpdate/Logs/lux.log.1 # 3.0.12 - 02/10/2014 - Corey Swertfager: # * Added contents of NIS 6 definitions' definfo.dat and usage.dat files. # * Replaced navmanout with one recompiled to remove symbols. # * Replaced VerifySignedFiles.command with version 2.0.12. # 3.0.13 - 02/21/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.13. # 3.0.14 - 04/18/2014 - Corey Swertfager: # * Added Norton Online Backup app info and logs for Etrack 3480221. # * Replaced ShowNortonAppInfo.command with version 3.0.16. # 3.0.15 - 05/30/2014 - Corey Swertfager: # * Now shows contents of logs in: # /Library/Application Support/Symantec/Silo/NFM/Licensing # 3.0.16 - 06/10/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.14. # 3.0.17 - 06/13/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.15. # 3.0.18 - 06/19/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.16. # 3.0.19 - 07/02/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.17. # 3.0.20 - 07/30/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.18. # 3.0.21 - 08/07/2014 - Corey Swertfager: # * Replaced DefineCurrentUserDesktopAndOS function with version 1.0.1 # to address Etrack incident 3437091. # 3.0.22 - 08/10/2014 - Corey Swertfager: # * Now includes info for non-root users whose home directories # are not in /Users: crontab entries, LiveUpdate date file info, # CrashReporter logs, and login window plists. # * Added DiagnosticReports logs to CrashReporter logs section. # * Suppressed error output from navmanout. # 3.0.23 - 08/10/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.19. # 3.0.24 - 08/11/2014 - Corey Swertfager: # * Replaced ShowNortonAppInfo.command with version 3.0.17. # 3.0.25 - 08/12/2014 - Corey Swertfager: # * Replaced GetComputerUsers function with version 1.0.1. # 3.0.26 - 08/19/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.20. # 3.0.27 - 08/25/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.21. # * Added to "AllFiles.txt" (also used by CopyFilesIntoFolder): # /Library/Application Support/.navx.startup # /Library/Application Support/.navx.startup-backup # /Library/Application Support/FSD.flag # /Library/Application Support/NAV.history # /Library/Application Support/NAVDiagnostic.log # /Library/Application Support/nat_* # /Library/Application Support/nav_* # /Library/Application Support/nis_* # /Library/Application Support/norton_* # /Library/Application Support/Norton* # /Library/Application Support/nsm_* # /Library/Extensions/Norton* # /Library/Internet Plug-Ins/NortonSafetyMinderBF.plugin # /Library/PrivateFrameworks/SymSEP.framework # /Library/PrivilegedHelperTools/com.symantec* # /System/Library/Extensions/ndcengine.kext # /usr/lib/libsymsea.*dylib # /usr/local/lib/libecomlodr.dylib # /usr/local/lib/libgecko3parsers.dylib # 3.0.28 - 08/28/2014 - Corey Swertfager: # * Now shows all Symantec logs found within /Library/Logs and # {each user's home directory}/Library/Logs. # * Adjusted report entry for files included in zip file. # 3.0.29 - 09/09/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.22. # 3.0.30 - 10/23/2014 - Corey Swertfager: # * Fixes for Etrack 3644239: by default shows only the last 5000 lines of # logs found in /Library/Logs and {each user's home directory}/Library/Logs # and only contents for those logs with extensions .crash, .log, or .txt. # * Added LinesToShowInLibraryLogs and SymantecLogExtensionsPattern # variables and is function. # * Removed duplicate output of SymantecTestPatchers.log. # * Updated CatFilesInList function: # - Changed note option from -n to -N. # - The -n option now limits number of lines output. # - Added separator when multiple files' contents are output. # - Added -S option to suppress separator. # * Updated help. # 3.0.31 - 12/29/2014 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.23. # 3.0.32 - 01/05/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.24. # 3.0.33 - 01/12/2015 - Corey Swertfager: # * Added to "AllFiles.txt" (also used by CopyFilesIntoFolder): # /usr/local/lib/libAPFeature.a # 3.0.34 - 02/09/2015 - Corey Swertfager: # * Removed from "AllFiles.txt" (also used by CopyFilesIntoFolder): # /usr/local/lib/libAPFeature.a # * Replaced VerifySignedFiles.command with version 2.0.25. # 3.0.35 - 04/08/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.26. # 3.0.36 - 04/09/2015 - Corey Swertfager: # * Added -r to call of VerifySignedFiles.command to show # every "resource envelope is obsolete" error. # 3.0.37 - 07/08/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.27. # 3.0.38 - 08/05/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.28. # * Now includes contents of last NumberOfLUXDebugLogsToInclude # LUX debug logs when LoggingTool.command is installed. # 3.0.39 - 08/31/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.29. # 3.0.40 - 11/19/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.30. # 3.0.41 - 12/07/2015 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.31. # * Added to report (Etrack 3870055, 3871026, and 3880976): # - Definitions avdefs group check. # - ErrorReporting submissions in Silo/NFM folders. # - Locale information. # - User home folders information. # - List of items in /. # - Permissions of /usr/local folders. # - Contents of SymDaemon log: # /Library/Application Support/Symantec/Silo/NFM/Daemon/messages.log # * Added files to zip archive: # - /private/var/log/system.log # - files_in_var_folders.txt, which lists all items in # /var/folders. # * Updated AddToZipArchive() function: added NewName and -d # options. # 3.0.42 - 01/25/2016 - Corey Swertfager: # * Added signing info for (Etrack 3867098): # /usr/local/lib/libecomlodr.dylib # * Added application versions (CFBundleShortVersionString) for # bundles in /Applications (Etrack 3896029). # * Updated "AllFiles.txt" (also used by CopyFilesIntoFolder) # (Etrack 3898531): # Added: # /usr/local/bin/MigrateQTF # /usr/local/bin/navx # /usr/local/bin/nortonscanner # /usr/local/bin/nortonsettings # /usr/local/bin/npfx # /usr/local/lib/libsymsea.*dylib # Changed: # /Library/Application Support/Symantec # /Library/PrivateFrameworks/SymAppKitAdditions.framework # /Library/PrivateFrameworks/SymAVScan.framework # /Library/PrivateFrameworks/SymBase.framework # /Library/PrivateFrameworks/SymConfidential.framework # /Library/PrivateFrameworks/SymDaemon.framework # /Library/PrivateFrameworks/SymFirewall.framework # /Library/PrivateFrameworks/SymInternetSecurity.framework # /Library/PrivateFrameworks/SymIPS.framework # /Library/PrivateFrameworks/SymIR.framework # /Library/PrivateFrameworks/SymLicensing.framework # /Library/PrivateFrameworks/SymNetworking.framework # /Library/PrivateFrameworks/SymOxygen.framework # /Library/PrivateFrameworks/SymPersonalFirewall.framework # /Library/PrivateFrameworks/SymScheduler.framework # /Library/PrivateFrameworks/SymSEP.framework # /Library/PrivateFrameworks/SymSharedSettings.framework # /Library/PrivateFrameworks/SymSubmission.framework # /Library/PrivateFrameworks/SymSystem.framework # /Library/PrivateFrameworks/SymUIAgent.framework # /Library/PrivateFrameworks/SymUIAgentUI.framework # /Library/PrivateFrameworks/SymWebKitUtils.framework # /System/Library/Extensions/NortonForMac.kext # /System/Library/Extensions/NPFKPI.kext # /System/Library/Extensions/SymDC.kext # /System/Library/Extensions/SymEvent.kext # /System/Library/Extensions/symfs.kext # /System/Library/Extensions/SymInternetSecurity.kext # /System/Library/Extensions/SymIPS.kext # /System/Library/Extensions/SymOSXKernelUtilities.kext # /System/Library/Extensions/SymPersonalFirewall.kext # to: # /Library/Application Support/Symantec* # /Library/PrivateFrameworks/Sym* # /System/Library/Extensions/Norton* # /System/Library/Extensions/NPFKPI.kext # /System/Library/Extensions/Sym* # /System/Library/Extensions/symfs.kext # 3.0.43 - 03/30/2016 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.32. # 3.0.44 - 05/02/2016 - Corey Swertfager: # * Added LoggingTool.command 1.0.7. # * Now uses LoggingTool.command in ScriptSupportDir if not # found in LUXToolsDir (Etrack 3939754). # * Added "/UIAgent" to SymantecLogGrepPattern. # 3.0.45 - 08/11/2016 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.33. # 3.0.46 - 09/22/2016 - Corey Swertfager: # * IRSpecial is now only run if NIS 4 or earlier is installed. # 3.0.47 - 10/19/2016 - Corey Swertfager: # * Replaced GetDefsDate.command with version 2.0.2. # * Added System Integrity Protection (rootless) status for OS 10.11 # and later (Etrack 3973223) to ShowProgramAndOSinfo() function. # * Added licensing logs (Etrack 3947085): # {each user's home directory}/Library/Logs/SymantecNISCC.log # /tmp/Logs/O2SpyLog # * Added SymDaemon sampling (Etrack 3931643). # 3.0.48 - 10/20/2016 - Corey Swertfager: # * Replaced GetDefsDate.command with version 2.0.3. # 3.0.49 - 10/20/2016 - Corey Swertfager: # * Broadened search for licensing logs (Etrack 3947085): # /tmp/Logs/O2Spy* # 3.0.50 - 01/13/2017 - Corey Swertfager: # * Added to zip archive: # /Library/Application Support/Symantec/Silo/NFM/LiveUpdate/datastore/luxds.dat # 3.0.51 - 02/01/2017 - Corey Swertfager: # * Removed Watermark for ftp zip posting. # 3.0.52 - 02/07/2017 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.34. # * Updated "AllFiles.txt" (also used by CopyFilesIntoFolder): added: # /Library/Application Support/com.symantec* # * Removed proxy login info from report (Etrack 4057747). # 3.0.53 - 04/12/2017 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.35. # * Added to zip archive in Licensing folder: # /Library/Application Support/Symantec/Silo/NFM/Licensing/NIS.* # 3.0.54 - 05/23/2017 - Corey Swertfager: # * Added Hardware UUID. # * Added avdefs group existence check. # 3.0.55 - 06/07/2017 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.36. # 3.0.56 - 10/16/2017 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.37. # 3.0.57 - 10/17/2017 - Corey Swertfager: # * Updated "AllFiles.txt" (also used by CopyFilesIntoFolder): added: # /Library/Preferences/com.symantec.* # 3.0.58 - 11/22/2017 - Corey Swertfager: # * Added EPMP to SymantecLogGrepPattern. # 3.0.59 - 02/12/2018 - Davee Nguyen: # * Replaced VerifySignedFiles.command with version 2.0.38. # 3.0.60 - 07/20/2018 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.39. # 3.0.61 - 07/23/2018 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.40. # 3.0.62 - 08/14/2018 - Corey Swertfager: # * Added collection of KextPolicy info (MACSYS-4065). # 3.0.63 - 08/16/2018 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.41. # 3.0.64 - 08/23/2018 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.42. # 3.0.65 - 09/12/2018 - Corey Swertfager: # * Updated "AllFiles.txt" (also used by CopyFilesIntoFolder): added: # /Applications/Application_DSP.app # /var/tmp/NFM # 3.0.66 - 09/29/2018 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.43. # 3.0.67 - 01/04/2019 - Corey Swertfager: # * Adjusted how libecomlodr.dylib signing is verified. # 3.0.68 - 01/14/2019 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.44. # 3.0.69 - 02/25/2019 - Corey Swertfager: # * Added Symantec entries (MACSYS-5874) found within: # /var/db/com.apple.xpc.launchd/disabled.*plist # 3.0.70 - 03/22/2019 - Corey Swertfager: # * Replaced ShowNortonAppInfo.command with version 3.0.18. # 3.0.71 - 04/17/2019 - Corey Swertfager: # * Limited plist content output to Info.plist files. # 4.0.0 - 05/13/2019 - Corey Swertfager: # * Script can now be run without SupportFiles folder. # * No longer runs GetURLDateProgram. # 4.0.1 - 05/15/2019 - Corey Swertfager: # * Added modification year and sorting to file listings. # 4.0.2 - 06/24/2019 - Corey Swertfager: # * Replaced LoggingTool.command with version 1.0.7. # 4.0.3 - 06/24/2019 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.45. # 4.0.4 - 06/24/2019 - Corey Swertfager: # * Replaced GetDefsDate.command with version 2.0.4. # * Replaced GetIPSsignaturesDate.command with version 2.0.1. # * Replaced VerifySignedFiles.command with version 2.0.46. # 4.0.5 - 06/26/2019 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.47. # 4.0.6 - 06/26/2019 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.48. # 4.0.7 - 06/26/2019 - Corey Swertfager: # * Replaced VerifySignedFiles.command with version 2.0.49. # 4.0.8 - 06/27/2019 - Corey Swertfager: # * Added support for multiple Silo directories. # * Removed LoggingTool.command. # * Added /private/var/log/system.log* to zip archive. # * No longer includes a list of files in /var/folders. # *** Variable Initializations *** PATH=/bin:/sbin:/usr/bin:/usr/sbin SymantecSupportDir="/Library/Application Support/Symantec" SiloRootDir="$SymantecSupportDir/Silo" NFMSiloDir="$SiloRootDir/NFM" ErrorReportingSubmissionsFolder="$SymantecSupportDir/ErrorReporting/Submissions" # ErrorReportingSubmissionsInNFMSiloFolder was only in NIS 6 ErrorReportingSubmissionsInNFMSiloFolder="$NFMSiloDir/ErrorReporting/Submissions" GetURLDateProgram="GetURLDate.command" InfoOutputBase="SymantecInfo" InfoOutputFile="$InfoOutputBase.txt" InfoOutputZip="$InfoOutputBase.zip" LinesToShowInDaemonErrorLog=20 LinesToShowInInstallLog=1600 LinesToShowInLibraryLogs=5000 LinesToShowInSystemLog=600 LiveUpdateSupportDirNIS4="/Library/Application Support/Norton Solutions Support/LiveUpdate" LiveUpdateSupportDirNIS5="$SymantecSupportDir/LiveUpdate" IRToolProgramName="IRTool" IRToolProgram="$LiveUpdateSupportDirNIS4/$IRToolProgramName" JavaLiveUpdateLog="$LiveUpdateSupportDirNIS4/liveupdt.log" KeychainFileLocation="/private/var/db/com.symantec" KeychainFileName="Symantec.keychain" KeychainFile="$KeychainFileLocation/$KeychainFileName" LANG="" LiveUpdate6Log="$LiveUpdateSupportDirNIS5/liveupdate.log" LiveUpdate6LogArchive="$LiveUpdateSupportDirNIS5/liveupdate.log.zip" LUDateFile="/Library/Preferences/Network/com.Symantec.LiveUpdate.plist" LUXLogForNortonZone="/var/log/luxtool.log" LUXLogForNortonZoneBackup="/var/log/luxtool.log.1" LUXLogName="lux.log" NIS6LUDir="$NFMSiloDir/LiveUpdate" NIS6LULogDir="$NIS6LUDir/Logs" NAVSubInfoProgram="xView" # xView was written by Nick Uchida NISSubInfoProgram="xxView" # xxView was written by Nick Uchida NOBLUSupportDir="/Library/Application Support/Norton Online Backup" NortonAppInfoProgram="ShowNortonAppInfo.command" NumberOfLUXDebugLogsToInclude=3 PublicVersion=true # Symantec Endpoint Protection debug log: SEPsupportDir="$SymantecSupportDir/SMC" SEPlogDir="$SEPsupportDir/debug" SEPlogFileName="smc_debug.log" SEPlogFile="$SEPlogDir/$SEPlogFileName" ScriptSupportDirName="SupportFiles" ShowQuitMessage=true TestPatchersLogFileName="SymantecTestPatchers.log" SymantecLogExclusionGrepPattern="/LiveUpdateAdminUtility|/$TestPatchersLogFileName" SymantecLogExtensionsPattern='\.crash$|\.log$|\.txt$' SymantecLogGrepPattern='/com\.norton|/com\.symantec|EPMP|/LiveUpdate|/Norton|/Sym|/UIAgent' SystemLog="/private/var/log/system.log" TestPatchersLogFile="/Library/Logs/$TestPatchersLogFileName" VarFolderListFileName="files_in_var_folders.txt" ZIP="/usr/bin/zip" # *** Function Declarations *** AddLiveUpdateFiles() { # Usage: AddLiveUpdateFiles # Summary: Add contents LiveUpdate logs to report and # add logs and datastores to zip archive. # local Datastore local Log local Logs local SiloDir AssignSymantecSupportFolderVariables # --- Add to report: LUX log for Norton Zone ECHOL "LUX logs for Norton Zone" echo "\"$LUXLogForNortonZoneBackup\"" >>"$TempBody" echo "" >>"$TempBody" if [ -f "$LUXLogForNortonZoneBackup" ] ; then cat "$LUXLogForNortonZoneBackup" >>"$TempBody" 2>/dev/null else echo "The log file does not exist." >>"$TempBody" fi echo "" >>"$TempBody" echo "\"$LUXLogForNortonZone\"" >>"$TempBody" echo "" >>"$TempBody" if [ -f "$LUXLogForNortonZone" ] ; then cat "$LUXLogForNortonZone" >>"$TempBody" 2>/dev/null else echo "The log file does not exist." >>"$TempBody" fi # --- Add to report: LiveUpdate 5 log ECHOL "NIS 4 and earlier LiveUpdate log" echo "\"$JavaLiveUpdateLog\"" >>"$TempBody" echo "" >>"$TempBody" if [ -f "$JavaLiveUpdateLog" ] ; then cat "$JavaLiveUpdateLog" >>"$TempBody" 2>/dev/null else echo "The log file does not exist." >>"$TempBody" fi # --- Add to report: LiveUpdate 6 log ECHOL "NIS 5 LiveUpdate log" echo "\"$LiveUpdate6Log\"" >>"$TempBody" echo "" >>"$TempBody" if [ -f "$LiveUpdate6Log" ] ; then cat "$LiveUpdate6Log" >>"$TempBody" 2>/dev/null else echo "The log file does not exist." >>"$TempBody" fi # --- Add to zip archive: LiveUpdate 6 log and log archive AddToZipArchive "$LiveUpdate6Log" -d "LiveUpdate/NIS_5" AddToZipArchive "$LiveUpdate6LogArchive" -d "LiveUpdate/NIS_5" # --- Add to report and to zip archive: NIS 6 and later LiveUpdate logs ECHOL "NIS 6 and later LiveUpdate DefUtils log" CatFilesInList -N -x "/var/log/du.log" # If NIS 6 debug LUX exists and has content if [ -s "$NIS6LULogDir/devlux.log" ] ; then ECHOL -b "NIS 6 text dev log" CatFilesInList -N -x "$NIS6LULogDir/devlux.log" fi if [ "$LiveUpdateLogDirsInSiloDirs" ] ; then for SiloDir in $LiveUpdateLogDirsInSiloDirs ; do SiloFolderName=`echo "$SiloDir" | awk -F / '{print $6}'` ECHOL "NIS 6 and later LiveUpdate SQL log in $SiloFolderName Silo" Log=`echo "$LiveUpdateSQLLogsInSiloDirs" | grep "$SiloDir"` if [ -f "$Log" ] ; then echo "$Log" >>"$TempBody" echo "" >>"$TempBody" sqlite3 "$Log" ".dump" 2>/dev/null >>"$TempBody" else echo "Log not found" >>"$TempBody" fi ECHOL "NIS 6 and later LiveUpdate LUX debug logs in $SiloFolderName Silo" Logs=`echo "$LUXDebugLogs" | grep "$SiloDir"` if [ "$Logs" ] ; then echo "Newest to oldest:" >>"$TempBody" echo "" >>"$TempBody" echo "$Logs" >>"$TempBody" for Log in $Logs ; do echo "" >>"$TempBody" echo "----- `basename "$Log"` -----" >>"$TempBody" echo "" >>"$TempBody" cat "$Log" >>"$TempBody" AddToZipArchive "$Log" -d "LiveUpdate/$SiloFolderName" done else echo "No logs were found" >>"$TempBody" fi ECHOL "NIS 6 and later LiveUpdate LUX text log ($LUXLogName) in $SiloFolderName Silo" Log=`echo "$LUXTextLogs" | grep "$SiloDir"` if [ -f "$Log" ] ; then echo "$Log" >>"$TempBody" echo "" >>"$TempBody" cat "$Log" >>"$TempBody" AddToZipArchive "$Log" -d "LiveUpdate/$SiloFolderName" else echo "Log not found" >>"$TempBody" fi done else ECHOL "NIS 6 and later LiveUpdate logs" echo "No logs were found" >>"$TempBody" fi for Log in $LUXRolloverTextLogs ; do AddToZipArchive "$Log" -d "LiveUpdate/$SiloFolderName" done # --- Add to zip archive: /Library/Application Support/Symantec/Silo/*/LiveUpdate/datastore/luxds.dat for Datastore in $InstalledDatastores ; do SiloFolderName=`echo "$Datastore" | awk -F / '{print $6}'` AddToZipArchive "$Datastore" -d "LiveUpdate/$SiloFolderName" done } AddToZipArchive() { # Usage: AddToZipArchive SourceFileOrFolder [-d] NewName # Summary: Adds file or folder to zip archive. If NewName is passed, the # file or folder copied will be renamed to NewName; if -d is also # passed, file or folder will be copied into folder named NewName # instead. If NewName contains slashes (/), path folders will be # created. # local DestDir="" local DoCreateFolder=false local NewName="" local SourceBase="" local SourceFileOrFolder="" ! $DoCreateZipArchive && return while [ "$1" ] ; do case "$1" in -d) DoCreateFolder=true ;; *) if [ -z "$SourceFileOrFolder" ] ; then SourceFileOrFolder="$1" SourceBase=`basename "/$1"` else NewName="$1" fi ;; esac shift done if [ "$NewName" ] ; then $DoCreateFolder && NewName="$NewName/$SourceBase" else NewName="$SourceBase" fi [ -e "$SourceFileOrFolder" ] && ditto "$SourceFileOrFolder" "$TempSymantecInfoFolder/$NewName" 2>/dev/null } AssignSymantecSupportFolderVariables() { # Usage: AssignSymantecSupportFolderVariables # Summary: Set variable values for items in Symantec support folder. # local SavedIFS="$IFS" DatastoreFileName="luxds.dat" [ -z "$SymantecSupportDir" ] && SymantecSupportDir="/Library/Application Support/Symantec" [ -z "$SiloRootDir" ] && SiloRootDir="$SymantecSupportDir/Silo" InstalledDatastores=`ls -d1 "$SiloRootDir/"*"/LiveUpdate/datastore/$DatastoreFileName" 2>/dev/null | sort -f` InstalledDatastoreDirs="" IFS=$'\n' # Set IFS to newlines for File in $InstalledDatastores ; do InstalledDatastoreDirs="$InstalledDatastoreDirs `dirname "$File"`" done InstalledDatastoreDirs=`echo "$InstalledDatastoreDirs" | grep .` DefinitionsInSiloDirs=`ls -d1 "$SiloRootDir/"*"/Definitions" 2>/dev/null | sort -f` DefinitionsInSiloDirsToShow="$SiloRootDir/*/Definitions" LicensingInSiloDirs=`ls -d1 "$SiloRootDir/"*"/Licensing" 2>/dev/null | sort -f` LicensingInSiloDirsToShow="$SiloRootDir/*/Licensing" LiveUpdateLogDirsInSiloDirs=`ls -d1 "$SiloRootDir/"*"/LiveUpdate/Logs" 2>/dev/null | sort -f` LiveUpdateSQLLogsInSiloDirs=`ls -d1 "$SiloRootDir/"*"/LiveUpdate/Logs/LiveUpdateLog" 2>/dev/null | sort -f` SymDaemonLogs="$SymantecSupportDir/Daemon/error.log `ls -d1 "$SiloRootDir/"*"/Daemon/messages.log" 2>/dev/null`" LUXTextLogs=`ls -d1 "$SiloRootDir/"*"/LiveUpdate/Logs/$LUXLogName" 2>/dev/null | sort -f` LUXRolloverTextLogs=`ls -d1 "$SiloRootDir/"*"/LiveUpdate/Logs/$LUXLogName.1" 2>/dev/null | sort -f` # Obtain list of NumberOfLUXDebugLogsToInclude debug logs in each LiveUpdate silo LUXDebugLogs="" for LogDir in $LiveUpdateLogDirsInSiloDirs ; do LogNumber=$NumberOfLUXDebugLogsToInclude # Find logs from newest to oldest for Log in `ls -t "$LogDir" 2>/dev/null | egrep -xe "devlux_[0-9]+\.log"` ; do # If log has contents if [ -s "$LogDir/$Log" ] ; then (( LogNumber-- )) LUXDebugLogs="$LUXDebugLogs $LogDir/$Log" fi if [ $LogNumber = 0 ] ; then break fi done done LUXDebugLogs=`echo "$LUXDebugLogs" | grep .` IFS="$SavedIFS" } CatFilesInList() { # Usage1: CatFilesInList [-b] [-N] [-n number] [-q] [-S] [-v pattern] [-R] path [ending] # Usage2: CatFilesInList [-b] [-N] [-n number] [-q] [-S] [-v pattern] -l list # Usage3: CatFilesInList [-b] [-N] [-n number] [-q] [-S] [-v pattern] -x path # Summary: Shows contents of files that match `ls path*ending`, with # separator '>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<' between # each file. # For Usage1 and Usage2, shows contents of files that match # `find path | grep -ie "ending$"`. # For Usage2, files in list are used, with each path on a newline. # For Usage3, only exact file name is used. # For plist files, only indented entries are shown. # Options: # -b Search only the basename of paths when using the -v option. # -N Show "NOTE" instead of "ERROR" when passed file does not exist # or is a folder. # -n # Only show last number of lines. Not applicable for plist files. # -q Do not show error message if no matching files are found. # -S Do not print separator between each file. # -v # Exclude paths that match pattern, where pattern is an extended # regular expression. Note that the whole path is searched unless # the -b option is also passed. # Note: A blank line is printed at end except when -q is passed # and no files match. No blank line is printed at beginning. # local DoSearchFullPathForExclusions=true local DoShowError=true local ErrorText=ERROR local ExclusionPattern="" local File local Files="" local FilesPurged="" local GrepPattern="" local GrepLoginPattern="Proxy username is|Proxy password is" local MaxLines="" local NumberOfFiles=0 local Separator='>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<' while [ $# -gt 0 ] ; do case "$1" in -b) DoSearchFullPathForExclusions=false ;; -N) ErrorText="NOTE" ;; -n) # If value passed after -n is a positive integer if is int "$2" 1 ; then MaxLines="$2" shift fi ;; -q) DoShowError=false ;; -S) Separator="" ;; -v) ExclusionPattern="$2" shift ;; *) break ;; esac shift done if [ "z$1" = z-l ] ; then Files="$2" elif [ "z$1" = z-R ] ; then Files=`find "$2" 2>/dev/null | grep -ie "$3$"` elif [ "z$1" = z-x ] ; then Files="$2" elif [ "$2" ] ; then Files=`ls "$1"*"$2" 2>/dev/null` elif [ "$1" ] ; then Files=`ls "$1"* 2>/dev/null` fi IFS=$'\n' # Set IFS to newlines if [ -n "$ExclusionPattern" ] ; then if $DoSearchFullPathForExclusions ; then Files=`printf "%s" "$Files" | egrep -ve "$ExclusionPattern"` else for File in $Files ; do # If filename does not match exclusion pattern, retain it in the list if [ -z "`basename "/$File" | egrep -e "$ExclusionPattern"`" ] ; then FilesPurged="$FilesPurged $File" fi done Files=`printf "%s" "$FilesPurged" | grep .` fi fi if [ -z "$Files" ] ; then if $DoShowError ; then echo "There were no matching items." >>"$TempBody" echo "" >>"$TempBody" fi return fi Files=`printf "%s" "$Files" | sort -f` NumberOfFiles=`echo "$Files" | grep -c .` for File in $Files ; do [ $NumberOfFiles -gt 1 -a -n "$Separator" ] && printf "%s\n\n" "$Separator" >>"$TempBody" echo "$File" >>"$TempBody" echo "" >>"$TempBody" if [ -d "$File" ] ; then echo "$ErrorText: That is a folder, so its contents will not be shown." >>"$TempBody" echo "" >>"$TempBody" continue elif [ ! -f "$File" ] ; then echo "$ErrorText: That file does not exist." >>"$TempBody" echo "" >>"$TempBody" continue fi cp -f "$File" "$TempFile" # If a plist if [ "`printf "%s" "$File" | grep -i '\.plist$'`" ] ; then plutil -convert xml1 "$TempFile" 2>/dev/null 1>&2 if [ $? != 0 ] ; then echo "ERROR: File could not be converted by plutil. Perhaps it is damaged." >>"$TempBody" echo "" >>"$TempBody" continue fi GrepPattern='^<' # Else if an xml file elif [ "`printf "%s" "$File" | grep -i '\.xml$'`" ] ; then # GrepPattern='^<' # No longer filter out lines that begin with < GrepPattern="" else GrepPattern="" fi if [ -s "$TempFile" ] ; then if [ "$GrepPattern" ] ; then cat "$TempFile" 2>/dev/null | tr '\015' '\012' | cat -v | grep -v "$GrepPattern" | egrep -ve "$GrepLoginPattern" >>"$TempBody" elif [ "$MaxLines" ] ; then cat "$TempFile" 2>/dev/null | tr '\015' '\012' | cat -v | egrep -ve "$GrepLoginPattern" | tail -n $MaxLines "$TempFile" 2>/dev/null >>"$TempBody" else cat "$TempFile" 2>/dev/null | tr '\015' '\012' | cat -v | egrep -ve "$GrepLoginPattern" >>"$TempBody" fi [ "`tail -n 1 "$TempBody" | grep -e .`" ] && echo "" >>"$TempBody" [ "`tail -n 1 "$TempBody" | grep -e .`" ] && echo "" >>"$TempBody" fi done } CreateFinalReport() { # If appending report onto an existing file if [ -f "$ReportFile" ] ; then cat "$TempHeader" "$TempBody" >>"$ReportFile" echo "Appended report onto:" echo "$ReportFile" echo if $DoOpen ; then echo "Opening that file..." echo open -e "$ReportFile" fi return fi # --- Add to zip archive: all files/folders passed to GatherSymantecInfo.command IFS=$'\n' # Set IFS to newlines for EachToAdd in `echo "$FilesToAddToZipArchive" | sort -f | uniq` ; do AddToZipArchive "$EachToAdd" done if [ -z "$ZipFilePath" ] ; then ZipFileDir="$UserDesktop" ZipFilePath="$ZipFileDir/$InfoOutputZip" fi CurrentDir=`pwd` # Save initial directory location cd "$TempSymantecInfoFolder" FilesAdded=`find * 2>/dev/null | sort -f` if [ "$FilesAdded" ] ; then # --- Add to report: list of files other than report that are in the zip archive NumberOfFilesAdded=`printf "%s" "$FilesAdded" | grep -c .` ECHOL "Additional file`[ $NumberOfFilesAdded -gt 1 ] && echo s` included with this report" echo "$FilesAdded" | awk '{print " "$0}' >>"$TempBody" fi # Combine temporary report header and body into report file within report archive folder cat "$TempHeader" "$TempBody" >"$TempSymantecInfoFolder/$InfoOutputFile" chmod -R 777 "$TempSymantecInfoFolder" chmod 666 "$TempSymantecInfoFolder/$InfoOutputFile" # Create temporary zip file of report archive folder rm -f "$TempFolder/$InfoOutputZip" 2>/dev/null "$ZIP" -qqr "$TempFolder/$InfoOutputZip" * 2>/dev/null cd "$CurrentDir" chown "$UserThatLoggedIntoComputer" "$TempFolder/$InfoOutputZip" 2>/dev/null 1>&2 chgrp staff "$TempFolder/$InfoOutputZip" 2>/dev/null 1>&2 chmod 777 "$TempFolder/$InfoOutputZip" 2>/dev/null 1>&2 # Move report archive to destination if [ ! -d "$ZipFileDir" ] ; then mkdir -p "$ZipFileDir" chmod 777 "$ZipFileDir" fi mv -f "$TempFolder/$InfoOutputZip" "$ZipFilePath" 2>/dev/null if [ "$ZipFilePath" = "$UserDesktop/$InfoOutputZip" -a -d "$UserDesktop" ] ; then echo "Symantec and system information was output and compressed into $InfoOutputZip" echo "on the Desktop. Please send that file to Symantec." if $DoOpen ; then mv -f "$TempSymantecInfoFolder/$InfoOutputFile" "$UserDesktop" echo echo "Opening the report..." open -e "$UserDesktop/$InfoOutputFile" fi else echo "Symantec info report archive was created at:" echo echo `ShowFullFilePath -P "$ZipFilePath"` fi echo } DefineCurrentUserDesktopAndOS() { # Usage: DefineCurrentUserDesktopAndOS [-d] [-o] [-u] [exit_code] # Summary: Assigns values to the following variables: # OSXmajorVersion # OSXVersion # UserDesktop # UserHomeDir # UserThatLoggedIntoComputer # If one of them could not be defined, login window is active, # or UserDesktop is not a directory, then an error message is # shown and this script is exited with exit_code or with 78 if # exit_code was not passed. # Options: # -d Don't show error and don't exit if Desktop is not a directory. # -o Don't show error and don't exit if OS version could not be # determined. # -u Don't show error and don't exit if login window is active or # if active user could not be determined. # exit_code # The exit code to use when an error occurs. The default is 78. # Exit code must be an integer in range 0-255. # # History: 1.0.1 - 08/07/2014 - Corey Swertfager: # * Revised the way the user's home directory is determined. # * Added definition of UserHomeDir. # * Added exit_code option. # * The -d option no longer prevents exiting with an error # when login window is active or when active user could # not be determined; use the -u to prevent that. # local DoShowDesktopError=true local DoShowLoginWindowActiveOrNoActiveUserError=true local DoShowOSVersionError=true local ErrorString="" local ExitValue=78 while [ $# -gt 0 ] ; do case "$1" in -d) DoShowDesktopError=false ;; -o) DoShowOSVersionError=false ;; -u) DoShowLoginWindowActiveOrNoActiveUserError=false ;; *) ExitValue="$1" ;; esac shift done OSXVersion=`cat /System/Library/CoreServices/SystemVersion.plist 2>/dev/null | tr '\015' '\012' | grep . | grep -A1 'ProductVersion' | tail -n 1 | grep '10\.' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` OSXmajorVersion=`printf "%s" "$OSXVersion" | awk -F . '{print $2}'` UserDesktop="" UserHomeDir="" UserThatLoggedIntoComputer=`printf "open\nshow State:/Users/ConsoleUser\nq\n" | scutil | tr '\015' '\012' | awk '{print $1$2$3}' | grep 'Name:.' | tail -n 1 | awk -F : '{print $2}'` if [ "z$UserThatLoggedIntoComputer" = zloginwindow ] ; then $DoShowLoginWindowActiveOrNoActiveUserError && ErrorString="WARNING: The login window is active." elif [ -z "$UserThatLoggedIntoComputer" ] ; then $DoShowLoginWindowActiveOrNoActiveUserError && ErrorString="WARNING: There is no user logged in or active user could not be determined." else UserHomeDir=`echo $(eval echo ~"$UserThatLoggedIntoComputer")` # If home directory is not a directory or could not be evaluated if [ ! -d "$UserHomeDir" -o -n "`printf "%s" "$UserHomeDir" | grep '^~'`" ] ; then UserHomeDir="" $DoShowDesktopError && ErrorString="$ErrorString WARNING: Could not determine home directory for user $UserThatLoggedIntoComputer." else UserDesktop="$UserHomeDir/Desktop" if [ -f "$UserDesktop" ] ; then $DoShowDesktopError && ErrorString="$ErrorString WARNING: $UserDesktop is a file instead of a directory." elif [ ! -d "$UserDesktop" ] ; then $DoShowDesktopError && ErrorString="$ErrorString WARNING: User Desktop folder ($UserDesktop) could not be found." fi fi fi # If OS major version could not be determined if [ -z "$OSXmajorVersion" ] ; then $DoShowOSVersionError && ErrorString="$ErrorString WARNING: Mac OS version could not be determined." fi if [ "$ErrorString" ] ; then echo "$ErrorString" | grep . echo " `basename "$0"` aborted." [ "`ExitScript "$ExitValue" 2>/dev/null`" ] && ExitScript "$ExitValue" || exit "$ExitValue" fi } ECHOL() { # Usage: ECHOL [-a] [-b] [string] # Summary: Appends separator with a blank line before and after to # TempBody file. If string is passed, ItemNumber + string # is written to header and body and ItemNumber is incremented. # Blank line is not written before if last line in TempBody # was blank. # Options: # -a Suppress blank line after separator. # -b Suppress blank line before separator. # string String is print after separator. # local EchoAfter=true local EchoBefore=true local StringToShow="" while [ "$1" ] ; do case "$1" in -a) EchoAfter=false ;; -b) EchoBefore=false ;; *) StringToShow="$1" ;; esac shift done if [ -s "$TempBody" ] ; then [ -z "`tail -n 1 "$TempBody" | grep -e .`" ] && EchoBefore=false fi $EchoBefore && echo "" >>"$TempBody" echo "---------------------------------------------------------------------------" >>"$TempBody" if [ "$StringToShow" ] ; then echo "" >>"$TempBody" echo "$ItemNumber. $StringToShow" >>"$TempBody" # If there is a colon at the end of string passed, remove it for table of contents [ "`printf "%s" "$StringToShow" | grep ':$'`" ] && StringToShow=`printf "%s" "$StringToShow" | awk '{print substr($0,1,length($0)-1)}'` echo "$ItemNumber. $StringToShow" >>"$TempHeader" let ItemNumber=$ItemNumber+1 fi $EchoAfter && echo "" >>"$TempBody" } ExitScript() { # Usage: ExitScript [-b] [-e] [exit_number [error_string]] # Summary: Checks to see if ShowQuitMessage and RunScriptAsStandAlone # variables are set to true. If so, a message is displayed; # otherwise, no message is displayed. The script is then # exited and passes exit_number to exit command. If no # exit_number is passed, then 0 is passed to exit command. If # a non-integer is passed as exit_number, 255 is passed to # exit command. If error_string is passed, it is printed to # to standard out before exiting and is padded by blank lines # if error_string is not "". Pass -b before exit_number to # suppress beginning padding line, -e to suppress ending # padding line, both to suppress both. TempFolder is also deleted. # local PadBeginning=true local PadEnd=true cd / rm -rf "$TempFolder" 2>/dev/null while [ "$1" ] ; do case "$1" in -b) PadBeginning=false ;; -e) PadEnd=false ;; *) break ;; esac shift done if [ $# -gt 1 ] ; then if [ -z "$2" ] ; then PadBeginning=false PadEnd=false fi $PadBeginning && echo printf "%s\n" "$2" $PadEnd && echo fi if [ "z$ShowQuitMessage" = ztrue -a "z$RunScriptAsStandAlone" = ztrue ] ; then [ $# -lt 2 -o \( $PadEnd = false -a -n "$2" \) ] && echo echo "NOTE: If you double-clicked this script, quit Terminal application now." [ $PadEnd = true -o -z "$2" ] && echo fi [ -z "$1" ] && exit 0 [ -z "`expr "$1" / 1 2>/dev/null`" ] && exit 255 || exit $1 } GetAdminPassword() { # Usage: GetAdminPassword [$1] # Argument: $1 - Prompt for password. If true is passed, a user that # is not root will always be asked for a password. If # something other than true is passed or if nothing is # passed, then a user that is not root will only be # prompted for a password if authentication has lapsed. # Summary: Gets an admin user password from the user so that # future sudo commands can be run without a password # prompt. The script is exited with a value of 1 if # the user enters an invalid password or if the user # is not an admin user. If the user is the root user, # then there is no prompt for a password (there is # no need for a password when user is root). # NOTE: Make sure ExitScript function is in the script. # # If root user, no need to prompt for password [ "`whoami`" = "root" ] && return 0 echo # If prompt for password if [ "$1" = "true" -o "$1" = "true" ] ; then sudo -k # Make sudo require a password the next time it is run echo "You must be an admin user to run this script." fi # A dummy sudo command to get password sudo -p "Please enter your admin password: " date 2>/dev/null 1>&2 if [ ! $? = 0 ] ; then # If failed to get password, alert user and exit script echo "You entered an invalid password or you are not an admin user. Script aborted." ExitScript 1 fi } GetComputerUsers() { # Usage: GetComputerUsers [-r] [volume] # # Version: 1.0.1 # # Summary: Defines the following variables: # # ComputerUsers # ComputerUsersHomeDirs # ComputerUsersHomeDirsAndRootDir # ComputerUsersTable # # Omitted are users whose home directories contain no Library # directory and users that are not root whose home directory is # /var/root. If volume is passed and there is no /Users on that # volume, variables are all set to "". ComputerUsersTable is a # list of users and their home directories, separated by tabs. # # Note: This function must be run as root to find all users. When an # OS X volume other than / is passed or if the dscl program fails # or does not exist, non-root users that do not have their home # directories in /Users are not included and root's home directory # is assumed to be /var/root. # # History: 1.0.1 - 08/11/2014 - Corey Swertfager: # * Added ComputerUsersTable variable assignment. # * Now always includes root user in case this function # is not run as root. # * Added volume argument. # local CurrentDir local GCUHomeDir local CGLibraryDir local CGLibraryDirs local GCUUser local GCUUsers local SavedIFS="$IFS" local VolumePassed="$1" ComputerUsers="" ComputerUsersHomeDirs="" ComputerUsersHomeDirsAndRootDir="" ComputerUsersTable="" # If a directory other than / is passed if [ -d "$VolumePassed" -a ! "$VolumePassed" -ef / ] ; then # If not an OS X volume, skip it [ ! -d "$VolumePassed/Users" ] && return CurrentDir=`pwd` cd "$VolumePassed" CGLibraryDirs=`ls -d Users/*/Library 2>/dev/null | grep -v 'Users/Shared'` cd "$CurrentDir" # If no Library folders were found, skip [ -z "$CGLibraryDirs" ] && return CGLibraryDirs="$CGLibraryDirs var/root/Library" IFS=' ' for CGLibraryDir in $CGLibraryDirs ; do GCUHomeDir="/`dirname "$CGLibraryDir"`" GCUUser=`basename "$GCUHomeDir"` ComputerUsersHomeDirs="$ComputerUsersHomeDirs $GCUHomeDir" ComputerUsers="$ComputerUsers $GCUUser" ComputerUsersTable="$ComputerUsersTable $GCUUser $GCUHomeDir" done else GCUUsers=`dscl . list /Users 2>/dev/null | egrep '^[[:alnum:]]' | egrep -vx 'daemon|nobody'` if [ -z "$GCUUsers" ] ; then GCUUsers="`ls /Users | egrep '^[[:alnum:]]' | grep -vx Shared` root" fi IFS=' ' for GCUUser in $GCUUsers ; do GCUHomeDir=`echo $(eval echo ~"$GCUUser")` # If home directory could not be evaluated if [ "`printf "%s" "$GCUHomeDir" | grep '^~'`" ] ; then continue elif [ "$GCUUser" != root ] ; then if [ ! -d "$GCUHomeDir/Library" ] ; then continue elif [ "$GCUHomeDir" = /var/root ] ; then continue fi fi ComputerUsers="$ComputerUsers $GCUUser" ComputerUsersHomeDirs="$ComputerUsersHomeDirs $GCUHomeDir" ComputerUsersTable="$ComputerUsersTable $GCUUser $GCUHomeDir" done fi IFS="$SavedIFS" ComputerUsers=`echo "$ComputerUsers" | grep . | sort -f | uniq` ComputerUsersHomeDirs=`echo "$ComputerUsersHomeDirs" | grep / | sort -f | uniq` ComputerUsersHomeDirsAndRootDir="/ $ComputerUsersHomeDirs" ComputerUsersTable=`echo "$ComputerUsersTable" | grep / | sort -f | uniq` } is() { # Usage: is [-e] class string [low [high]] # Arguments: -e = write error to standard error; must be passed first # class = character class # string = string to check # low = lowest acceptable value # high = highest acceptable value # Summary: Checks to see if string is entirely made up of characters # in class. Class may be alnum, alpha, int (integer), lower, # num (only digits), upper, or xnum (hexadecimal). # If class is int or num, low and/or high can also be checked. # If want to check for a maximum value but don't need to check # for a minimum value, pass "" to low and an integer to high. # Returns 0 if all characters are in class (and if int or num # is in range low-high), 1 otherwise. # local ShowIsError=false if [ "z$1" = z-e ] ; then ShowIsError=true shift fi if [ -z "$2" ] ; then $ShowIsError && echo "ERROR: Nothing was passed to is function to check." >&2 return 1 fi case "$1" in alnum) if [ "`echo "z$2" | tr -d '[:alnum:]'`" ] ; then $ShowIsError && echo "ERROR: Not all alphanumeric: \"$2\"" >&2 return 1 fi ;; alpha) if [ "`echo "z$2" | tr -d '[:alpha:]'`" ] ; then $ShowIsError && echo "ERROR: Not all alphabetical: \"$2\"" >&2 return 1 fi ;; int) if [ -z "`expr "$2" / 1 2>/dev/null`" ] ; then $ShowIsError && echo "ERROR: Not an integer: \"$2\"" >&2 return 1 else if is int "$3" ; then if [ $2 -lt $3 ] ; then $ShowIsError && echo "ERROR: $2 is less than minimum $3." >&2 return 1 fi elif [ "$3" ] ; then $ShowIsError && echo "ERROR: Minimum value passed is not an integer: \"$3\"." >&2 return 1 fi if is int "$4" ; then if [ $2 -gt $4 ] ; then $ShowIsError && echo "ERROR: $2 is greater than maximum $4." >&2 return 1 fi elif [ "$4" ] ; then $ShowIsError && echo "ERROR: Maximum value passed is not an integer: \"$4\"." >&2 return 1 fi fi ;; lower) if [ "`echo "z$2" | tr -d '[:lower:]'`" ] ; then $ShowIsError && echo "ERROR: Not all lowercase letters: \"$2\"" >&2 return 1 fi ;; num) if [ "`echo "0$2" | tr -d '[:digit:]'`" ] ; then $ShowIsError && echo "ERROR: Not all digits: \"$2\"" >&2 return 1 else if is num "$3" ; then if [ $2 -lt $3 ] ; then $ShowIsError && echo "ERROR: $2 is less than minimum $3." >&2 return 1 fi elif [ "$3" ] ; then $ShowIsError && echo "ERROR: Minimum value passed is not all digits: \"$3\"." >&2 return 1 fi if is num "$4" ; then if [ $2 -gt $4 ] ; then $ShowIsError && echo "ERROR: $2 is greater than maximum $4." >&2 return 1 fi elif [ "$4" ] ; then $ShowIsError && echo "ERROR: Maximum value passed is not all digits: \"$4\"." >&2 return 1 fi fi ;; upper) if [ "`echo "Z$2" | tr -d '[:upper:]'`" ] ; then $ShowIsError && echo "ERROR: Not all uppercase letters: \"$2\"" >&2 return 1 fi ;; xnum) if [ "`echo "a$2" | tr -d '[:xdigit:]'`" ] ; then $ShowIsError && echo "ERROR: Not all hexidecimal: \"$2\"" >&2 return 1 fi ;; "") $ShowIsError && echo "ERROR: No class was passed to is function." >&2 return 1 ;; *) $ShowIsError && echo "ERROR: Invalid class: \"$1\" Class must be alnum, alpha, int (integer), lower, num (only digits), upper, or xnum (hexadecimal)." >&2 return 1 ;; esac return 0 } ProcessArguments() { # Usage: ProcessArguments [ --OptionTakesUnparsedArgument=string ] [ --OptionIsOneArgument=string ] "$@" # # Version: 1.0.1 # # Summary: Processes arguments passed to script. Arguments beginning with a # single hyphen (-) are parsed into separate options except when an # argument is negative integer. Arguments beginning with two hypens # are treated as one argument; if the argument contains is an equals # sign (=), the string after the first "=" is treated as a separate # argument (i.e., the value assigned to the double-hyphen argument). # # For each --OptionTakesUnparsedArgument passed before "$@", the string # after "=" is used as an option that takes the next argument in full # without parsing it (see examples below); string must be a hyphen # followed by a single character. # # For each --OptionIsOneArgument passed before "$@", the string after # "=" is used as an option that should be treated as a single argument. # This is useful when processing an argument that begins with a single # hyphen to avoid having that argument parsed into separate options. # The referenced option cannot be embedded within other options (see # final example below). # # "$@" must be the last argument passed to ProcessArguments. Put all custom # option handling between "--- Customized argument handling begins here ---" # and "--- Customized argument handling ends here ---". # # Note: ProcessArgumentsNextArgument may be called to verify and obtain the # next argument after or before a given option; see that function's usage # for more details. OriginalArgumentNumber can be used to determine if # two arguments were originally passed within the same string of options. # # Examples: These examples have expanded the arguments passed as "$@". # # ProcessArguments -ab -c # Would process three arguments: -a, -b, and -c # ProcessArguments --ab -c # Would process two arguments: --ab and -c # ProcessArguments --equation=a=b+c # Would process two arguments: --equation and a=b+c # ProcessArguments -10 # Would process one argument: -10 # ProcessArguments -10a # Would process three arguments: -1, -0, -a # ProcessArguments --OptionTakesUnparsedArgument=-e -e -ger # Would process two arguments: -e and -ger # ProcessArguments --OptionTakesUnparsedArgument=-e -peer # Would process three arguments: -p, -e, and er # ProcessArguments --OptionTakesUnparsedArgument=-e --OptionTakesUnparsedArgument=-t -eter -ter # Would process four arguments: -e, ter, -t, and er # ProcessArguments --OptionIsOneArgument=-hi -hi # Would process one argument: -hi # ProcessArguments --OptionIsOneArgument=-hi -his # Would process three arguments: -h, -i, and -s # # History: 1.0.1 - 06/23/2013 - Corey Swertfager: # * Added processing of options within a string that begins # with a single hyphen. # * Added --OptionTakesUnparsedArgument option. # * Added --OptionIsOneArgument option. # local ArgList="" local ArgsToAdd local ArgWasAdded=false local CurrentArgNumber=1 local CurrentArgument local CurrentCharacter local DoNotParseNextArgument=false local NextArgument="" local NumberOfArgumentsPassed local NumberOfArgumentsToUse=0 local OptionToAdd local OriginalArgumentNumber=0 local OriginalArgumentNumberList="" local RemainingOptionsInString local TableOfOptionsWithoutParsing="*** Each option in this table will have its succeeding argument left unparsed. ***" local TableOfUndividedArguments="*** Each item in this table should each be treated as single argument. ***" while [ "$1" ] ; do case "$1" in --OptionIsOneArgument) ExitScript 99 "WARNING: Bad use of --OptionIsOneArgument passed to ProcessArguments: \"$1\"" ;; --OptionIsOneArgument=*) OptionToAdd=`printf "%s" "$1" | awk '{match($0,"=") ; print substr($0,RSTART+1)}'` [ -z "$OptionToAdd" ] && ExitScript 99 "WARNING: Bad use of --OptionIsOneArgument passed to ProcessArguments: \"$1\"" TableOfUndividedArguments="$TableOfUndividedArguments $OptionToAdd" ;; --OptionTakesUnparsedArgument|--OptionTakesUnparsedArgument=*) OptionToAdd=`printf "%s" "$1" | awk '{match($0,"=") ; print substr($0,RSTART+1)}'` [ -z "`printf "%s" "$OptionToAdd" | grep -xe '-.'`" ] && ExitScript 99 "WARNING: Bad use of --OptionTakesUnparsedArgument passed to ProcessArguments: \"$1\"" TableOfOptionsWithoutParsing="$TableOfOptionsWithoutParsing $OptionToAdd" ;; *) break ;; esac shift done NumberOfArgumentsPassed=$# while [ $# != 0 ] ; do let OriginalArgumentNumber=$OriginalArgumentNumber+1 # If argument is in the list of arguments whose next argument should not be parsed if [ "`printf "%s" "$1" | grep -xF "$TableOfOptionsWithoutParsing"`" ] ; then ArgsToAdd="$1" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" DoNotParseNextArgument=true # Else if argument is in the list of arguments that should be treated as one argument elif [ "`printf "%s" "$1" | grep -xF "$TableOfUndividedArguments"`" ] ; then ArgsToAdd="$1" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" else case "$1" in -|-?) # If argument was a hyphen or a hyphen followed by a single character ArgsToAdd="$1" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" DoNotParseNextArgument=false ;; --*) # If a value was passed to the option that begins with -- if [ "`printf "%s" "$1" | grep =`" ] ; then # Add the option and its value as separate arguments ArgsToAdd="`printf "%s" "$1" | awk -F = '{print $1}'` `printf "%s" "$1" | awk '{match($0,"=") ; print substr($0,RSTART+1)}'`" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber $OriginalArgumentNumber" else ArgsToAdd="$1" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" fi DoNotParseNextArgument=false ;; -*) # If argument should not be parsed or is a negative integer if [ $DoNotParseNextArgument = true -o -z "`printf "%s" "$1" | awk '{print substr($0,2)}' | tr -d '[:digit:]'`" ] ; then # Treat argument as a single argument ArgsToAdd="$1" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" DoNotParseNextArgument=false else # Parse string into separate arguments ArgsToAdd="" RemainingOptionsInString=`printf "%s" "$1" | awk '{print substr($0,2)}'` while [ "$RemainingOptionsInString" ] ; do CurrentCharacter=`printf "%s" "$RemainingOptionsInString" | awk '{print substr($0,1,1)}'` # Prefix the character with a hyphen and add as an argument if [ "$ArgsToAdd" ] ; then ArgsToAdd="$ArgsToAdd -$CurrentCharacter" else ArgsToAdd="-$CurrentCharacter" fi OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" RemainingOptionsInString=`printf "%s" "$RemainingOptionsInString" | awk '{print substr($0,2)}'` # If this is an option whose next string should not be parsed if [ "`printf "%s" "$TableOfOptionsWithoutParsing" | grep -xe "-$CurrentCharacter"`" ] ; then # If string has characters remaining after that option if [ "$RemainingOptionsInString" ] ; then # Add remainder of string as the unparsed string argument ArgsToAdd="$ArgsToAdd $RemainingOptionsInString" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" else # Use next argument passed as unparsed string argument DoNotParseNextArgument=true fi break fi done fi ;; *) ArgsToAdd="$1" OriginalArgumentNumberList="$OriginalArgumentNumberList $OriginalArgumentNumber" DoNotParseNextArgument=false ;; esac fi if $ArgWasAdded ; then ArgList="$ArgList $ArgsToAdd" else ArgList="$ArgsToAdd" fi ArgWasAdded=true shift done if [ $NumberOfArgumentsPassed -gt 0 ] ; then # Add a non-blank line to ArgList in case last argument passed was "" ArgList="$ArgList TheEnd" OriginalArgumentNumberList=`echo "$OriginalArgumentNumberList" | grep .` NumberOfArgumentsToUse=`printf "%s" "$ArgList" | grep "" -c` let NumberOfArgumentsToUse=$NumberOfArgumentsToUse-1 fi # --- Customized argument handling begins here --- DoCreateZipArchive=true DoOpen=false DoPromptForKey=false # Changed to false in version 2.0.0 DoRunVerifySignedFiles=true FilesToAddToZipArchive="" OptionForDefineCurrentUserDesktopAndOS="" ReportFile="" ShowUnlimitedLinesInLogs=false ZipFileDir="" ZipFilePath="" while [ $CurrentArgNumber -le $NumberOfArgumentsToUse ] ; do CurrentArgument=`printf "%s" "$ArgList" | head -n $CurrentArgNumber | tail -n 1` OriginalArgumentNumber=`echo "$OriginalArgumentNumberList" | head -n $CurrentArgNumber | tail -n 1` case "$CurrentArgument" in -a) ProcessArgumentsNextArgument -f -P ReportFile="$NextArgumentFullPath" DoCreateZipArchive=false OptionForDefineCurrentUserDesktopAndOS="-d" ;; -H) ShowUsage 0 ;; -h) ShowHelp 0 ;; -k) DoPromptForKey=false ;; -o) DoOpen=true ;; -s) DoRunVerifySignedFiles=false ;; -u) ShowUnlimitedLinesInLogs=true ;; -V) echo $Version exit 0 ;; -z) ProcessArgumentsNextArgument -r [ -z "$NextArgument" ] && ShowUsage 2 "ERROR: No zip file path was specified after -z." ZipFilePath=`ShowFullFilePath -P "$NextArgument"` # If not an existing file or folder if [ -z "$ZipFilePath" ] ; then # If argument passed after -z begins with a hyphen, show error [ "`printf "%s" "$NextArgument" | grep -e '^-'`" ] && ShowUsage 2 "ERROR: Zip file path specified after -z cannot begin with a hyphen (-): \"$NextArgument\"" ZipFileDir=`dirname "$NextArgument"` [ -d "$ZipFileDir" ] && ZipFileDir=`ShowFullFilePath -P "$ZipFileDir"` ZipFilePath="$ZipFileDir`[ "z$ZipFileDir" != z/ ] && echo /``basename "$NextArgument"`" # Else if a folder was passed elif [ -d "$ZipFilePath" ] ; then ZipFileDir="$ZipFilePath" ZipFilePath="$ZipFileDir`[ "z$ZipFileDir" != z/ ] && echo /`$InfoOutputZip" else ZipFileDir=`dirname "$ZipFilePath"` fi DoOpen=false ;; "") : ;; *) PathToAdd=`ShowFullFilePath -P "$CurrentArgument"` if [ -f "$PathToAdd" ] ; then FilesToAddToZipArchive="$FilesToAddToZipArchive $PathToAdd" else ShowUsage 2 "ERROR: Invalid argument: \"$CurrentArgument\"." fi ;; esac let CurrentArgNumber=$CurrentArgNumber+1 done if [ "$ZipFilePath" ] ; then DoCreateZipArchive=true DoOpen=false OptionForDefineCurrentUserDesktopAndOS="-d" ReportFile="" fi # --- Customized argument handling ends here --- } ProcessArgumentsNextArgument() { # Usage: ProcessArgumentsNextArgument [exit_code] [-F | -P] [-p | -r ] [operator] # # Version: 1.0.0 # # Arguments: exit_code Pass integer in range 0-255 to ShowUsage when next # argument is missing or invalid. If exit_code is not # specified, 0 is assumed. # # -F Assign the full logical path to NextArgumentFullPath. # This is the default. ShowFullFilePath function must # be included in script. If no operator was passed, -E # is the assumed operator. # # -P Assign the full physical path to NextArgumentFullPath. # ShowFullFilePath function must be included in script. # If no operator was passed, -e is the assumed operator. # # -p Get previous argument instead of next argument. If # there is no previous argument, sets NextArgument to "" # and returns 1. # # -r Return 1 instead of exiting script if there is no next # argument. Sets NextArgument to "". # # operator Operator used to test next argument: # -d Folder # -E File, folder, or link # -e File, folder, or link to an existing file/folder # -f File # -i [min [max]] # Integer in range min-max; pass "" to min and # an integer to max if there is no minimum but # a maximum is desired; pass "" to to both min # and max if passing another option after the -i # option. Also tests to see if the value of the # next argument is out of range for the currently # running version of Mac OS. # -L Link; does not check to see if link is broken # unless -P option was also passed # -l Link to an existing file/folder # -n Non-null string # # Summary: Called by ProcessArguments 1.0.1 or later to assign values to: # # CurrentArgNumber # NextArgument # NextArgumentFullPath # NextArgumentOriginalArgumentNumber # # using pre-existing values of: # # ArgList # CurrentArgNumber # CurrentArgument # OriginalArgumentNumberList # NumberOfArgumentsToUse # # Returns 0 if next or previous argument was assigned to NextArgument, # CurrentArgNumber was incremented (or decremented if -p was passed), # and NextArgumentOriginalArgumentNumber was assigned. # # Assigns "" to NextArgument and NextArgumentFullPath and returns 1 if # -p is passed and there is no previous argument, or if -r is passed # and there is no next argument; otherwise, calls ShowUsage to show # error message and exit script if operator test fails or if there is # no next or previous argument. # # Note: ShowFullFilePath function must be included in script in order to # assign a value to NextArgumentFullPath. # # Examples: ProcessArgumentsNextArgument # Returns 0 if there was a next argument; otherwise, passes 0 to # ShowUsage and displays error message about missing argument. # ProcessArgumentsNextArgument -r # Returns 0 if there was a next argument; otherwise, assigns "" to # NextArgument and NextArgumentFullPath, then returns 1. # ProcessArgumentsNextArgument 2 -d # Returns 0 if NextArgument was set to a folder; otherwise, passes # 2 to ShowUsage and displays error message if the next argument is # missing or is not a folder. # ProcessArgumentsNextArgument 3 -r -d # Returns 0 if NextArgument was set to a folder. If the next argument # is missing, assigns "" to NextArgument and NextArgumentFullPath, # then returns 1. If next argument is not a folder, passes 3 to # ShowUsage and displays error message. # ProcessArgumentsNextArgument 4 -i 1 # Returns 0 if NextArgument was set to an integer; otherwise, passes # 4 to ShowUsage and displays error message if the next argument is # missing, is not an integer, or is less than 1. # ProcessArgumentsNextArgument -i "" 100 5 # Returns 0 if NextArgument was set to an integer; otherwise, passes # 5 to ShowUsage and displays error message if the next argument is # missing, is not an integer, or is greater than 100. # ProcessArgumentsNextArgument -i "" "" 6 # Returns 0 if NextArgument was set to an integer; otherwise, passes # 6 to ShowUsage and displays error message if the next argument is # missing or is not an integer. # local DoShowMissingError=true local DirectionText=after local ExitCode=0 local ErrorText="" local GoToPreviousArgument=false local Max local Min local NextArgumentOriginal local PathOption="" local TestOperator="" NextArgumentFullPath="" while [ "$1" ] ; do case "$1" in -d) ErrorText="folder" TestOperator="$1" ;; -E) ErrorText="file, folder, or link" TestOperator="$1" ;; -e) ErrorText="file or folder" TestOperator="$1" ;; -F) PathOption="$1" if [ -z "$ErrorText" ] ; then ErrorText="file, folder, or link" TestOperator="-E" fi ;; -f) ErrorText="file" TestOperator="$1" ;; -i) ErrorText="integer" TestOperator="$1" Min="$2" Max="$3" shift 2 ;; -L) ErrorText="link" TestOperator="$1" [ "z$PathOption" = "z-P" ] && ErrorText="unbroken link" ;; -l) ErrorText="unbroken link" TestOperator="-L" ;; -n) ErrorText="non-null string" TestOperator="$1" ;; -P) PathOption="$1" if [ -z "$ErrorText" ] ; then ErrorText="file or folder" TestOperator="-e" elif [ "$ErrorText" = "link" ] ; then ErrorText="unbroken link" fi ;; -p) GoToPreviousArgument=true DirectionText=before ;; -r) DoShowMissingError=false ;; *) ExitCode=`printf "%s" "$1" | tr -d -c "[:digit:]"` [ -z "$ExitCode" ] && ExitCode=0 ;; esac shift done if $GoToPreviousArgument ; then if [ $CurrentArgNumber -gt 1 ] ; then let CurrentArgNumber=$CurrentArgNumber-1 NextArgument=`printf "%s" "$ArgList" | head -n $CurrentArgNumber | tail -n 1` NextArgumentOriginalArgumentNumber=`echo "$OriginalArgumentNumberList" | head -n $CurrentArgNumber | tail -n 1` else NextArgument="" NextArgumentFullPath="" return 1 fi # Else if there are no more arguments in ArgList elif [ $CurrentArgNumber = $NumberOfArgumentsToUse ] ; then if $DoShowMissingError ; then ShowUsage $ExitCode "ERROR: Nothing was passed after $CurrentArgument" >&2 else NextArgument="" NextArgumentFullPath="" return 1 fi else let CurrentArgNumber=$CurrentArgNumber+1 NextArgument=`printf "%s" "$ArgList" | head -n $CurrentArgNumber | tail -n 1` NextArgumentOriginalArgumentNumber=`echo "$OriginalArgumentNumberList" | head -n $CurrentArgNumber | tail -n 1` fi NextArgumentFullPath=`ShowFullFilePath $PathOption "$NextArgument"` if [ "z$ErrorText" = zinteger ] ; then NextArgumentOriginal="$NextArgument" if [ -z "$NextArgument" ] ; then ShowUsage $ExitCode "ERROR: Argument passed $DirectionText $CurrentArgument is not an integer: \"$NextArgumentOriginal\"" >&2 # Else if argument contains something other than a hyphen or digits elif [ "`printf "%s" "$NextArgument" | tr -d "[:digit:]-"`" ] ; then ShowUsage $ExitCode "ERROR: Argument passed $DirectionText $CurrentArgument is not an integer: \"$NextArgumentOriginal\"" >&2 # Else if argument contains a hyphen that is not at the beginning elif [ "`printf "%s" "$NextArgument" | grep '..*-'`" ] ; then ShowUsage $ExitCode "ERROR: Argument passed $DirectionText $CurrentArgument is not an integer: \"$NextArgumentOriginal\"" >&2 fi NextArgument=`expr "$NextArgument" / 1 2>/dev/null` test "$NextArgumentOriginal" -eq "$NextArgument" 2>/dev/null if [ $? != 0 ] ; then ShowUsage $ExitCode "ERROR: Value passed $DirectionText $CurrentArgument is out of range for this OS: $NextArgumentOriginal" >&2 fi # If minimum value was specified if [ "$Min" ] ; then [ $NextArgument -lt $Min ] && ShowUsage $ExitCode "ERROR: Value passed $DirectionText $CurrentArgument ($NextArgumentOriginal) is less than minimum value ($Min)." >&2 fi # If maximum value was specified if [ "$Max" ] ; then [ $NextArgument -gt $Max ] && ShowUsage $ExitCode "ERROR: Value passed $DirectionText $CurrentArgument ($NextArgumentOriginal) is greater than maximum value ($Max)." >&2 fi elif [ "z$ErrorText" = "zfile, folder, or link" ] ; then [ ! -e "$NextArgument" -a ! -L "$NextArgument" ] && ShowUsage $ExitCode "ERROR: Argument passed $DirectionText $CurrentArgument is not a $ErrorText: \"$NextArgument\"" >&2 elif [ "z$ErrorText" = "zunbroken link" ] ; then if [ ! -L "$NextArgument" ] ; then ShowUsage $ExitCode "ERROR: Argument passed $DirectionText $CurrentArgument is not a link: \"$NextArgument\"" >&2 # Else if link is broken elif [ ! -e "$NextArgument" ] ; then ShowUsage $ExitCode "ERROR: The target of the link passed $DirectionText $CurrentArgument does not exist: \"$NextArgument\"" >&2 fi elif [ "$ErrorText" ] ; then [ ! $TestOperator "$NextArgument" ] && ShowUsage $ExitCode "ERROR: Argument passed $DirectionText $CurrentArgument is not a $ErrorText: \"$NextArgument\"" >&2 fi if [ "$PathOption" ] ; then if [ -z "$NextArgumentFullPath" ] ; then if [ -L "$NextArgument" ] ; then ShowUsage $ExitCode "ERROR: The target of the link passed $DirectionText $CurrentArgument does not exist: \"$NextArgument\"" >&2 else ExitScript $ExitCode "WARNING: ShowFullFilePath function could not resolve path for: \"$NextArgument\"" >&2 fi fi fi return 0 } ShowCrontabEntries() { # Usage: ShowCrontabEntries # Summary: Shows crontab entries. # Note: User must be root when calling this function. ComputerUsers must be # defined using GetComputerUsers function before running this function. # local CurrentDir CurrentDir="`pwd`" # Save initial directory location CronTable="/private/var/at/tabs OS 10.5 /private/var/cron/tabs OS 10.4 and earlier" IFS=' ' for Line in $CronTable ; do CRONDIR=`echo "$Line" | awk -F " " '{print $1}'` Label=`echo "$Line" | awk -F " " '{print $2}'` CrontabEntryExists=false echo echo "--- Crontab entries in $CRONDIR (for $Label):" if [ ! -d "$CRONDIR" ] ; then echo echo " Directory not found: $CRONDIR" continue fi cd "$CRONDIR" # List each crontab, pipe through grep command for User in `ls * 2>/dev/null` ; do # If not a valid user, skip [ -z "`echo "$ComputerUsers" | grep -xe "$User"`" ] && continue Entries=`crontab -l -u "$User" 2>/dev/null` if [ "$Entries" ] ; then CrontabEntryExists=true echo echo "------ For user $User:" echo echo "$Entries" fi done ! $CrontabEntryExists && echo " No entries found." done cd "$CurrentDir" # Return to intial directory } ShowFullFilePath() { # Usage: ShowFullFilePath [-a] [-P | -L] [-e] Path [[-e] Path] # Version: 1.0.2 # Summary: Prints the full path starting at / of Path if Path exists # and Path is accessible by the user calling this function. # Run this function as root to ensure full path displaying. # If there is more than one existing file that matches the # name, then only the first path that the shell matches is # printed unless -a or more than one path is specified. # You can specify wild card characters ? and * and other # argument operators in the Path (e.g., "../*", "a?.txt", # "[ab]*"). # Options: -a Show all matching paths, sorted alphanumerically. If # -P is not passed, the same file may be shown multiple # times if there is more than one matching link that # points to it. # -e # Treat argument after -e as a path. Use -e to treat # -a, -e, -L, or -P as a path. # -L Show logical path, even if a file pointed to by a link # doesn't exist. This is the default. # -P Show physical path. If a link points to a file that # does not exist, the path won't be shown. # History: 1.0.1 - Added -e option and ability to pass multiple paths. # Arguments can now be passed in any order. # Fixed error that could occur when resolving links # with long paths. # 1.0.2 - Modified for case-sensitive volume compatibility. # Made temporary file names more distinctive. # local SFFPArgCount=$# local SFFPCurrentDir local SFFPCurrentDirTranslated local SFFPEachLine local SFFPEachPath local SFFPFile local SFFPLDir local SFFPLLinkLS local SFFPLLinkPath local SFFPLPath local SFFPPathOption=-L local SFFPSaveIFS="$IFS" local SFFPShowAll=false local SFFPTempBase=/private/tmp/ShowFullFilePath-`/usr/bin/basename "$0"`-`/bin/date +"%Y%m%d%H%M%S"` local SFFPTempFile="$SFFPTempBase.tmp" local SFFPTempFile2="$SFFPTempBase-2.tmp" /bin/rm -f "$SFFPTempFile" 2>/dev/null while [ $SFFPArgCount != 0 ] ; do case "$1" in -a) SFFPShowAll=true ;; -L|-P) SFFPPathOption="$1" ;; *) [ "z$1" = z-e ] && shift if [ "$1" ] ; then [ -s "$SFFPTempFile" ] && SFFPShowAll=true /usr/bin/printf "%s\n" "$1" >>"$SFFPTempFile" fi ;; esac shift let SFFPArgCount=$SFFPArgCount-1 done [ ! -s "$SFFPTempFile" ] && return SFFPCurrentDir=`/bin/pwd` SFFPCurrentDirTranslated=`/bin/pwd $SFFPPathOption 2>/dev/null` if [ ! -d "$SFFPCurrentDirTranslated" ] ; then /bin/rm -f "$SFFPTempFile" 2>/dev/null return fi cd "$SFFPCurrentDirTranslated" 2>/dev/null if [ $? != 0 ] ; then /bin/rm -f "$SFFPTempFile" 2>/dev/null return fi /usr/bin/printf "" >"$SFFPTempFile2" IFS=' ' for SFFPEachLine in `/bin/cat "$SFFPTempFile" 2>/dev/null` ; do cd "$SFFPCurrentDirTranslated" 2>/dev/null [ $? != 0 ] && break if [ "z$SFFPPathOption" = z-P ] ; then SFFPLPath="$SFFPEachLine" while [ -L "$SFFPLPath" ] ; do [ ! -e "$SFFPLPath" ] && break cd "`/usr/bin/dirname "$SFFPLPath" 2>/dev/null`" 2>/dev/null [ $? != 0 ] && break SFFPLDir=`/bin/pwd -P 2>/dev/null` [ ! -d "$SFFPLDir" ] && break SFFPLLinkLS=`/bin/ls -ld "$SFFPLPath" 2>/dev/null` [ -z "$SFFPLLinkLS" ] && break # If link or link target contains " -> " in its name if [ "`echo "z$SFFPLLinkLS" | grep ' -> .* -> '`" ] ; then SFFPLLinkPath=`/usr/bin/printf "%s" "$SFFPLLinkLS" | /usr/bin/awk -v THESTR="$SFFPLPath -> " '{ match($0,THESTR) ; print substr($0,RSTART+RLENGTH)}'` else SFFPLLinkPath=`echo "$SFFPLLinkLS" | awk -F " -> " '{print $2}'` fi # If link target begins with / if [ "`/usr/bin/printf "%s" "$SFFPLLinkPath" | grep '^/'`" ] ; then SFFPLPath="$SFFPLLinkPath" else SFFPLPath="$SFFPLDir/$SFFPLLinkPath" fi [ "`/usr/bin/printf "%s" "$SFFPLPath" | grep '^//'`" ] && SFFPLPath=`echo "$SFFPLPath" | /usr/bin/awk '{print substr($0,2)}'` done cd "$SFFPCurrentDirTranslated" 2>/dev/null [ $? != 0 ] && break if [ ! -e "$SFFPLPath" ] ; then $SFFPShowAll && continue || break fi SFFPEachPath="$SFFPLPath" else SFFPEachPath="$SFFPEachLine" fi if [ -d "$SFFPEachPath" ] ; then cd "$SFFPEachPath" 2>/dev/null if [ $? != 0 ] ; then $SFFPShowAll && continue || break fi SFFPFile="" elif [ -d "`/usr/bin/dirname "$SFFPEachPath" 2>/dev/null`" ] ; then cd "`/usr/bin/dirname "$SFFPEachPath" 2>/dev/null`" 2>/dev/null if [ $? != 0 ] ; then $SFFPShowAll && continue || break fi SFFPFile=`basename "$SFFPEachPath" 2>/dev/null` [ "z$SFFPFile" = z/ -o "z$SFFPFile" = z. -o "z$SFFPFile" = z.. ] && SFFPFile="" elif $SFFPShowAll ; then continue else break fi SFFPDir=`/bin/pwd $SFFPPathOption 2>/dev/null` if [ ! -d "$SFFPDir" ] ; then $SFFPShowAll && continue || break fi SFFPPath="$SFFPDir`[ "z$SFFPFile" != z -a "z$SFFPDir" != z/ -a "z$SFFPDir" != z// ] && echo /`$SFFPFile" if [ ! -e "$SFFPPath" -a ! -L "$SFFPPath" ] ; then $SFFPShowAll && continue || break fi [ "`echo "$SFFPPath" | grep '^//'`" ] && SFFPPath=`echo "$SFFPPath" | /usr/bin/awk '{print substr($0,2)}'` echo "$SFFPPath" >>"$SFFPTempFile2" # If neither option -a nor more than one path was passed, don't show any more names ! $SFFPShowAll && break done IFS=$SFFPSaveIFS [ -s "$SFFPTempFile2" ] && /usr/bin/sort -f "$SFFPTempFile2" | /usr/bin/uniq /bin/rm -f "$SFFPTempFile" "$SFFPTempFile2" 2>/dev/null cd "$SFFPCurrentDir" 2>/dev/null } ShowHelp() { # Usage: ShowHelp [$1] # Argument: $1 = Exit code. # Summary: Displays script usage and help then exits script. # If a number is passed to $1, then script exits with # that number; else, script is not exited. # echo " Usage1: $FullScriptName [-k] [-o] [-s] [-u] [file [file]] Usage2: $FullScriptName [-k] [-o] [-s] [-u] -a file Usage3: $FullScriptName [-k] [-s] [-u] [file [file]] -z path Summary: Gathers information about installed Symantec products and operating system into $InfoOutputZip on the Desktop. You will be prompted for your admin password. Options: -a Append report to file instead of creating a report on the Desktop. -k Bypass prompt for subscription key. As of $FullScriptName 2.0.0, the prompt has been removed. The -k option remains for legacy support. -o Open report file after it is generated. -s Skip verification of signed files. -u Show unlimited number of lines in logs. If -u is not specified, then the number of lines shown will be: Symantec daemon error log: $LinesToShowInDaemonErrorLog Installer log: $LinesToShowInInstallLog System log: $LinesToShowInSystemLog Logs in /Library/Logs: $LinesToShowInLibraryLogs -z Create zip file at path specified instead of creating $InfoOutputZip on Desktop. If path is an existing file, it will be overwritten. If path is an existing folder, $InfoOutputZip will be created in that folder. If path does not exist, a zip file will be created using the basename of the path as the file name; the dirname of the path will be used as the enclosing folder and will be created if it does not exist. The -a and -o options are ignored. Add file to $InfoOutputZip. Several files may be specified. " | more -E [ "$1" ] && exit $1 } ShowInstalledApplicationInfo() { local AppInfoWasShown local BuildToAdd local EachPath local iAntiVirusPlist local iAntiVirusPlistStrings local NortonAppDir local NortonAppDirName="Norton Solutions" local NortonOnlineBackup local NortonOnlineBackupDir local PathsOfApps local ProductTable local SafetyMinderPlist local SavedIFS="$IFS" local Stage2TextToShow local SupportPlist local SupportPlists local SymantecAppDir local SymantecAppDirName="Symantec Solutions" local SymantecRegistryDir local SymantecSupportDir local VersionToAdd local VPNAppName="Norton Secure VPN" local VPNPlist local VPNVersion local WCIDBundleBase local WCIDEngineBundle local WCIDEnginePlist local WCIDParentDir GetVersion() { # Usage: GetVersion String # Argument: String = Partial string from CFBundleGetInfoString. # Pass String without quotes to separate portions. # Summary: Echoes the version portion of String. # local StringToShow="" while [ "$1" ] ; do StringToShow="$1" shift done echo "$StringToShow" } ListInfoPlist() { # Usage: ListInfoPlist [-n] $1 $2 [$3] # Arguments: $1 = Full path of directory that contains file $2. # $2 = Name of file. # $3 = Name to display. # Summary: Displays contents of file's Contents/info.plist # If -n is passed as first argument, output is not indented. # local BuildVersion local CFBundleGetInfoString local CFBundleGetInfoStringAdjusted local CFBundleGetInfoStringAdjusted1 local CFBundleGetInfoStringAdjusted2 local CFBundleGetInfoStringAdjusted3 local CFBundleGetInfoStringAdjusted4 local CFBundleGetInfoStringAdjusted5 local FileNameToShow local FileWithNoExtension local IndentToAdd local ProductVersion local ThePlist if [ "z$1" = z-n ] ; then shift IndentToAdd="" else IndentToAdd=" " fi # If the file has .pkg extension or it is a symbolic link, ignore it if [ "z`echo "$1/$2" | grep "\.pkg"`" != "z" -o -L "$1/$2" ] ; then return fi FileWithNoExtension=`basename "$2" .app` if [ "$3" ] ; then FileNameToShow="$3" elif [ "z$FileWithNoExtension" = "zNorton Disk Doctor" ] ; then FileNameToShow="Norton Utilities" else FileNameToShow="$FileWithNoExtension" fi ThePlist=`ls -d "$1/$2/Contents/"[Ii]"nfo.plist" 2>/dev/null` # If file does not contain an info.plist, show if not a package if [ ! -f "$ThePlist" ] ; then if [ -f "$1/$FileWithNoExtension" ] ; then echo "$IndentToAdd$FileNameToShow (not a bundle - perhaps it's a pre-Hangar file)" echo fi return fi printf "$IndentToAdd$FileNameToShow " CFBundleGetInfoString=`grep -A1 '>CFBundleGetInfoString<' "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` # Set up CFBundleGetInfoStringAdjusted based on presence of paretheses if [ "$CFBundleGetInfoString" ] ; then CFBundleGetInfoStringAdjusted=`printf "%s" "$CFBundleGetInfoString" | grep "(" | awk '{print $1" "$2}' | tr -d ,` else # Use the line with parentheses to set CFBundleGetInfoStringAdjusted CFBundleGetInfoStringAdjusted=`grep "(" "$ThePlist" | awk '{print $1" "$2}' | tr -d ","` fi # If Norton Zone if [ "z$FileNameToShow" = "zNorton Zone" ] ; then ProductVersion=`grep -A 1 CFBundleShortVersionString "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` if [ "$ProductVersion" ] ; then # If there is a build field if [ "`echo "$ProductVersion" | awk -F . '{print $4}'`" ] ; then CFBundleGetInfoStringAdjusted="`echo "$ProductVersion" | awk -F . '{print $1"."$2"."$3" ("$4")"}'`" else CFBundleGetInfoStringAdjusted="`echo "$ProductVersion" | awk -F . '{print $1"."$2"."$3" (build unknown)"}'`" fi else CFBundleGetInfoStringAdjusted="(version unknown)" fi echo "$CFBundleGetInfoStringAdjusted" echo return # Else if there were no lines with parentheses elif [ -z "$CFBundleGetInfoStringAdjusted" ] ; then # Grab everything before first comma if [ "$CFBundleGetInfoString" ] ; then CFBundleGetInfoStringAdjusted=`printf "%s" "$CFBundleGetInfoString" | awk -F ',' '{print $1}'` else # Use the line with "Symantec Corp" to set CFBundleGetInfoStringAdjusted CFBundleGetInfoStringAdjusted=`grep "Symantec Corp" "$ThePlist" | awk -F '>' '{print $2}' | awk -F ',' '{print $1}'` fi CFBundleGetInfoStringAdjusted1=`echo "$CFBundleGetInfoStringAdjusted" | awk '{print $1}'` CFBundleGetInfoStringAdjusted2=`echo "$CFBundleGetInfoStringAdjusted" | awk '{print $2}'` CFBundleGetInfoStringAdjusted3=`echo "$CFBundleGetInfoStringAdjusted" | awk '{print $3}'` CFBundleGetInfoStringAdjusted4=`echo "$CFBundleGetInfoStringAdjusted" | awk '{print $4}'` CFBundleGetInfoStringAdjusted5=`echo "$CFBundleGetInfoStringAdjusted" | awk '{print $5}'` CFBundleGetInfoStringAdjusted=`GetVersion "$CFBundleGetInfoStringAdjusted1" "$CFBundleGetInfoStringAdjusted2" "$CFBundleGetInfoStringAdjusted3" "$CFBundleGetInfoStringAdjusted4" "$CFBundleGetInfoStringAdjusted5"` # If CFBundleGetInfoStringAdjusted is not null and contains no letters if [ "$CFBundleGetInfoStringAdjusted" -a -z "`echo "$CFBundleGetInfoStringAdjusted" | grep '[a-zA-Z]'`" ] ; then BuildVersion=`grep -A 1 BuildVersion "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` [ "$BuildVersion" ] && CFBundleGetInfoStringAdjusted="$CFBundleGetInfoStringAdjusted ($BuildVersion)" fi fi if [ -z "$CFBundleGetInfoStringAdjusted" ] ; then BuildVersion=`grep -A 1 BuildVersion "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` ProductVersion=`grep -A 1 CFBundleShortVersionString "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` if [ "$ProductVersion" ] ; then [ -z "$BuildVersion" ] && BuildVersion=`grep -A 1 CFBundleVersion "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` else ProductVersion=`grep -A 1 CFBundleVersion "$ThePlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` fi if [ "$ProductVersion" ] ; then [ -z "$BuildVersion" ] && BuildVersion="build unknown" CFBundleGetInfoStringAdjusted="$ProductVersion ($BuildVersion)" fi fi [ -z "$CFBundleGetInfoStringAdjusted" ] && CFBundleGetInfoStringAdjusted="(version unknown)" echo "$CFBundleGetInfoStringAdjusted" echo } ShowLooseInApplicationsFiles() { local EachLoose local EachLooseBase local EachLooseDir local EachLooseInfo local LooseInApplicationsFolder # If a limiting pattern was specified, skip output [ "$LimitOutputPattern" ] && return LooseInApplicationsFolder="`ls -d "$PathToUseAsPrefix/Applications/iAntiVirus.app" "$PathToUseAsPrefix/Applications/Norton"* "$PathToUseAsPrefix/Applications/Symantec"* 2>/dev/null | grep -vE '/Applications/Norton Solutions$|/Applications/Symantec Solutions$' | sort -f`" if [ -n "$LooseInApplicationsFolder" ] ; then echo "Loose in /Applications$VolumeText:" echo for EachLoose in $LooseInApplicationsFolder ; do EachLooseBase=`basename "$EachLoose"` EachLooseDir=`dirname "$EachLoose"` EachLooseInfo=`ListInfoPlist "$EachLooseDir" "$EachLooseBase"` if [ "$EachLooseInfo" ] ; then echo "$EachLooseInfo" else echo " $EachLooseBase`[ -L "$EachLoose" ] && echo " (symbolic link)"`" fi echo done fi } IFS=$'\n' # Set IFS to newlines NortonAppDir="/Applications/$NortonAppDirName" SymantecAppDir="/Applications/$SymantecAppDirName" NortonOnlineBackup="/Library/Application Support/Norton Online Backup/Norton Online Backup.app" echo if [ ! -d "$NortonAppDir" -a ! -d "$SymantecAppDir" ] ; then ShowLooseInApplicationsFiles if $DoShowMessageIfNotInstalled ; then echo "No $NortonAppDirName or $SymantecAppDirName found$VolumeText." echo fi else ShowLooseInApplicationsFiles AppInfoWasShown=false PathsOfApps=`ls -d "$NortonAppDir/LiveUpdate"* "$NortonAppDir/Norton "* "$NortonAppDir/Symantec "* "$NortonAppDir/Norton Utilities/Norton Disk Doctor"* 2>/dev/null | sort -f | uniq | grep -ie "$NortonAppDir/$LimitOutputPattern"` if [ -d "$NortonAppDir" -a ! -L "$NortonAppDir" -a -n "$PathsOfApps" ] ; then echo "Products installed in $NortonAppDirName$VolumeText:" echo for EachPath in $PathsOfApps ; do ListInfoPlist "`dirname "$EachPath"`" "`basename "$EachPath"`" done AppInfoWasShown=true fi PathsOfApps=`ls -d "$SymantecAppDir/LiveUpdate"* "$SymantecAppDir/Norton "* "$SymantecAppDir/SmallScanner.app" "$SymantecAppDir/Symantec "* "$SymantecAppDir/Norton Utilities/Norton Disk Doctor"* 2>/dev/null | sort -f | uniq | grep -ie "$SymantecAppDir/$LimitOutputPattern"` if [ -d "$SymantecAppDir" -a ! -L "$SymantecAppDir" -a -n "$PathsOfApps" ] ; then echo "Products installed in $SymantecAppDirName$VolumeText:" echo for EachPath in $PathsOfApps ; do ListInfoPlist "`dirname "$EachPath"`" "`basename "$EachPath"`" done AppInfoWasShown=true fi if ! $AppInfoWasShown ; then if $DoShowMessageIfNotInstalled ; then echo "No apps found in $NortonAppDirName or $SymantecAppDirName$VolumeText" [ -n "$LimitOutputPattern" ] && echo "that begin with pattern \"$LimitOutputPattern\"" echo fi fi fi if [ -d "$NortonOnlineBackup" ] ; then NortonOnlineBackupDir=`dirname "$NortonOnlineBackup"` echo "In \"$NortonOnlineBackupDir\"$VolumeText:" echo ListInfoPlist "$NortonOnlineBackupDir" "`basename "$NortonOnlineBackup"`" AppInfoWasShown=true fi if [ -d "/Library/Application Support/Symantec/SymQuickMenu/Norton Safety Minder QM.plugIn" -a \ -n "`echo "Norton Safety Minder QM.plugIn" | grep -ie "^$LimitOutputPattern"`" ] ; then echo "Installed in SymQuickMenu folder:" echo ListInfoPlist "/Library/Application Support/Symantec/SymQuickMenu" "Norton Safety Minder QM.plugIn" "Norton Safety Minder" fi # Show stage 2 build and other components' versions iAntiVirusPlist="/Applications/iAntivirus.app/Contents/Info.plist" iAntiVirusPlistStrings="/Applications/iAntivirus.app/Contents/Resources/English.lproj/InfoPlist.strings" SymantecSupportDir="/Library/Application Support/Symantec" SymantecRegistryDir="$SymantecSupportDir/Registry" SafetyMinderPlist="$SymantecSupportDir/Norton Safety Minder/Localization.bundle/Contents/Info.plist" VPNPlist="$SymantecSupportDir/$VPNAppName.app/Contents/Info.plist" WCIDEngineBundle="$SymantecSupportDir/WebFraud/WCIDEngine.bundle" WCIDEnginePlist="$WCIDEngineBundle/Contents/Info.plist" SupportPlists=`ls -d "$SymantecRegistryDir/"*".plist" 2>/dev/null | grep -ie "com\.symantec\.$LimitOutputPattern"` if [ -z "$LimitOutputPattern" ] ; then SupportPlists="$SupportPlists `ls -d "$iAntiVirusPlist" "$SafetyMinderPlist" "$WCIDEnginePlist" 2>/dev/null`" fi Stage2TextToShow="Stage 2 builds and other components: " SupportPlists=`echo "$SupportPlists" | sort -f | uniq | grep .` if [ "$SupportPlists" ] ; then echo "$Stage2TextToShow" Stage2TextToShow="" ProductTable="" for SupportPlist in $SupportPlists ; do # If iAntiVirus if [ "$SupportPlist" = "$iAntiVirusPlist" ] ; then VersionToAdd=`grep '>CFBundleShortVersionString<' -A1 "$iAntiVirusPlist" | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` BuildToAdd=`grep -a -e '^ CFBundleVersion' "$iAntiVirusPlistStrings" | tail -n 1 | awk -F '"' '{print $2}'` [ -z "$BuildToAdd" ] && BuildToAdd=`iconv --from-code UTF-16 --to-code UTF-8 "$iAntiVirusPlistStrings" 2>/dev/null | grep -a -e 'CFBundleVersion' | tail -n 1 | awk -F '"' '{print $2}'` [ -z "$BuildToAdd" ] && BuildToAdd="build unknown" # Add product info to list of products ProductTable="$ProductTable iAntiVirus $VersionToAdd ($BuildToAdd)" # Else if Norton Safety Minder 2.x elif [ "$SupportPlist" = "$SafetyMinderPlist" ] ; then # Add product name to list of products ProductTable="$ProductTable Norton Safety Minder" # Add product version to list of products ProductTable="$ProductTable `grep '>FullVersion<' -A1 "$SupportPlist" | grep 'string>' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}' | tail -n 1`" # Else if WCID engine elif [ "$SupportPlist" = "$WCIDEnginePlist" ] ; then WCIDParentDir=`dirname "$WCIDEngineBundle"` WCIDBundleBase=`basename "$WCIDEngineBundle"` # Add product info via ListInfoPlist to list of products ProductTable="$ProductTable `ListInfoPlist -n "$WCIDParentDir" "$WCIDBundleBase" "WCID Engine"`" # Add product version to list of products ProductTable="$ProductTable `grep '>FullVersion<' -A1 "$SupportPlist" | grep 'string>' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}' | tail -n 1`" else # Add product name to list of products ProductTable="$ProductTable `grep '>en<' -A1 "$SupportPlist" | grep 'string>' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}' | tail -n 1 | tr -d -c '[:alnum:] '`" # Add product version to list of products ProductTable="$ProductTable `grep '>Version<' -A1 "$SupportPlist" | grep 'string>' | grep -v '\*' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}' | tail -n 1`" fi done # 3.0.15 - only show items that begin with aphanumeric characters (those which have Name keys in their plists) echo "$ProductTable" | grep '^[[:alnum:]]' | sort -f | uniq | awk '{printf " %s\n\n", $0}' fi if [ -f "$VPNPlist" ] ; then if [ "$Stage2TextToShow" ] ; then echo "$Stage2TextToShow" fi VPNVersion=`cat "$VPNPlist" 2>/dev/null | tr '\015' '\012' | grep . | grep -A1 CFBundleShortVersionString | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` if [ -z "$VPNVersion" ] ; then VPNVersion="(could not determine version)" fi echo " $VPNAppName $VPNVersion" echo fi IFS="$SavedIFS" } ShowInstalledIPSSignaturesDates() { local IPSDir local IPSDirOld="/Library/Application Support/Symantec/IntrusionPrevention" local IPSDirs6=`ls -d "/Library/Application Support/Symantec/Silo/"*"/Definitions/symcdata/vulnprotectiondefs" 2>/dev/null` local SavedIFS="$IFS" local ShowIndividualFiles=false local TheFileToCheck="su-cr.md" GetSigsDate() { # Usage: GetSigsDate $1 # Argument: $1 = File from which to get date. # Summary: Gets the date from a file if it is a IPS def file. # Assigns date to SigsDate variable and returns 0 if # a date is found, else assigns NULL to SigsDate and # returns 1. # local ModificationDay local ModificationMonthText local ModificationTime local ModificationYear local ModifiedDateString local SigsBuild local SigsDay local SigsMonth="" local SigsMonthName local SigsYear local ModifiedDateString SigsDate="" # If $1 is not a file, return 1 test -f "$1" || return 1 # If $1 has a filename that begins with a period, return 1 test "`basename "$1" | awk '{print substr($0,1,1)}'`" = "." && return 1 ModifiedDateString=`hexdump -C -v -n 16 "$1" | head -n 1` ModifiedDateString=`cat "$1" | grep '.*' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` # If ModifiedDateString is null, return 1 [ -z "$ModifiedDateString" ] && return 1 # If ModifiedDateString is not a number, return 1 [ -z "`expr "$ModifiedDateString" / 1 2>/dev/null`" ] && return 1 SigsMonth=`echo "z$ModifiedDateString" | awk '{print substr($0,6,2)}'` SigsMonth=`expr $SigsMonth / 1` SigsDay=`echo "z$ModifiedDateString" | awk '{print substr($0,8,2)}'` SigsYear=`echo "z$ModifiedDateString" | awk '{print substr($0,2,4)}'` SigsBuild=`echo "z$ModifiedDateString" | awk '{print substr($0,10)}'` SigsBuild=`expr $SigsBuild / 1` # If file type was not correct, return 1 [ -z "$SigsMonth" ] && return 1 case $SigsMonth in 1) SigsMonthName=January ;; 2) SigsMonthName=February ;; 3) SigsMonthName=March ;; 4) SigsMonthName=April ;; 5) SigsMonthName=May ;; 6) SigsMonthName=June ;; 7) SigsMonthName=July ;; 8) SigsMonthName=August ;; 9) SigsMonthName=September ;; 10) SigsMonthName=October ;; 11) SigsMonthName=November ;; 12) SigsMonthName=December ;; esac ModificationYear=`ls -dlT "$1" | awk '{print $9}'` ModificationTime=`ls -dlT "$1" | awk '{print $8}'` ModificationDay=`ls -dlT "$1" | awk '{print $7}'` ModificationDay=`expr "$ModificationDay" / 1 2>/dev/null` # If ModificationDay is not a number (i.e., fields of ls output are reversed) if [ -z "$ModificationDay" ] ; then ModificationDay=`ls -dlT "$1" | awk '{print $6}'` ModificationMonthText=`ls -dlT "$1" | awk '{print $7}'` else ModificationMonthText=`ls -dlT "$1" | awk '{print $6}'` fi SigsDate="$SigsMonthName $SigsDay, $SigsYear - build $SigsBuild (`echo "$ModifiedDateString" | awk '{print substr($0,1,8)}'`), modified $ModificationMonthText $ModificationDay, $ModificationYear $ModificationTime" return 0 } ShowSigsDateForFileOrFolder() { # Usage: ShowSigsDateForFileOrFolder $1 # Argument: $1 = Name of file or folder to check # Summary: Shows IPS signatures date for file or folder passed. # local CurrentDir=`pwd` local SigsDate="" local SigFolders if [ -d "$1" -a $ShowIndividualFiles = false ] ; then cd "$1" for FileToCheck in `ls` ; do GetSigsDate "$FileToCheck" # If SigsDate was assigned, break test -n "$SigsDate" && break done if [ -n "$SigsDate" ] ; then echo "Date of IPS signatures in folder '$1':" echo " $SigsDate" else echo "No IPS signatures date was found in any file within folder: '$1'" fi echo elif [ -d "$1" -a $ShowIndividualFiles = true ] ; then cd "$1" for FileToCheck in `ls` ; do GetSigsDate "$FileToCheck" if [ -n "$SigsDate" ] ; then echo "Date of IPS signatures file '$1/$FileToCheck':" echo " $SigsDate" echo else # If filename does not begin with a period (is not invisible) if [ "`basename "$FileToCheck" | awk '{print substr($0,1,1)}'`" != "." ] ; then echo "No IPS signatures date was found in file: '$1`[ "z$1" != z/ ] && echo /`$FileToCheck'" echo fi fi done elif [ -f "$1" ] ; then GetSigsDate "$1" if [ -n "$SigsDate" ] ; then echo "Date of IPS signatures file '$1':" echo " $SigsDate" else echo "No IPS signatures date was found in file: $1" fi echo else echo "No such file or folder: '$1'" echo fi cd "$CurrentDir" } # If NIS 6 or later IPS signatures are installed if [ "$IPSDirs6" ] ; then IPSDirs="$IPSDirs6" # Else if NIS 5 or earlier IPS signatures are installed elif [ -d "$IPSDirOld" ] ; then IPSDirs="$IPSDirOld" else echo "Could not find any installed Vulnerability Protection (IPS) signatures." echo return fi RemainingDirsToCheck=`echo "$IPSDirs" | grep -c .` IFS=$'\n' for IPSDir in $IPSDirs ; do (( RemainingDirsToCheck-- )) SigFolders=`ls -d "$IPSDir/"*Signatures* "$IPSDir/"2* 2>/dev/null | sort -f` SigFolders=`ls -d "$IPSDir/"*Signatures* "$IPSDir/"2* 2>/dev/null | sort -f` cd "$IPSDir" 2>/dev/null if [ $? = 0 ] ; then echo "Vulnerability Protection (IPS) signatures in:" echo " \"$IPSDir\"" echo DefsFolderWereFound=false for EachSigFile in $SigFolders ; do DefsFolderWereFound=true ShowSigsDateForFileOrFolder "`basename "$EachSigFile"`" done $DefsFolderWereFound || printf "No signatures were found in that folder.\n\n" fi if [ $RemainingDirsToCheck -gt 0 ] ; then echo "-----" echo fi done IFS="$SavedIFS" } ShowInstalledVirusDefsDates() { local AntiVirusDirOld="/Library/Application Support/Norton Solutions Support/Norton AntiVirus" local AntiVirusDir2="/Library/Application Support/Symantec/AntiVirus" local AntiVirusDirs6=`ls -d "/Library/Application Support/Symantec/Silo/"*"/Definitions/virusdefs" 2>/dev/null` local DefsFolderWereFound local EachInstalledFolder local SavedIFS="$IFS" local ShowIndividualFiles=false GetDefsDate() { # Usage: GetDefsDate file # Summary: Gets the date from file if it is a virus def file. # Assigns date to DefsDate variable and returns 0 if # a date is found, else assigns NULL to DefsDate and # returns 1. # local DefsBuild="N/A" local DefsDay local DefsFolder local DefsYear local DefsMonth="" local DefsMonthName local FilePassed="$1" local FirstLine local Line local navlibxVersion local Signature4="NotSetYet" local Signature8="NotSetYet" local TempOtoolFile DefsDate="" # If not a file, return 1 [ -f "$FilePassed" ] || return 1 # If file passed has a filename that begins with a period, return 1 [ "`basename "/$FilePassed" | awk '{print substr($0,1,1)}'`" = "." ] && return 1 for Line in `hexdump -C -v -n 20 "$FilePassed"` ; do if [ "$Signature8" = "NotSetYet" ] ; then FirstLine="$Line" Signature4=`echo "z$Line" | awk '{print $2$3$4$5}'` Signature8=`echo "z$Line" | awk '{print $2$3$4$5$6$7$8$9}'` # Else if Signature4 = SYMC elif [ "z$Signature4" = z53594d43 ] ; then DefsMonth="`echo "z$FirstLine" | awk '{print $10}'`" DefsMonth="`printf %d 0x$DefsMonth`" DefsDay="`echo "z$FirstLine" | awk '{print $11}'`" DefsDay="`printf %d 0x$DefsDay`" DefsYear="`echo "z$FirstLine" | awk '{print $12}'`" DefsYear="`printf %d 0x$DefsYear`" DefsYear="`expr $DefsYear + 1900`" DefsBuild="`echo "z$FirstLine" | awk '{print $9$8$7$6}'`" DefsBuild="`printf "%d" 0x$DefsBuild`" break # Else if Signature8 = SYMPATCH elif [ "z$Signature8" = z53594d5041544348 ] ; then DefsMonth="`echo "z$Line" | awk '{print $2}'`" DefsMonth="`printf %d 0x$DefsMonth`" DefsDay="`echo "z$Line" | awk '{print $3}'`" DefsDay="`printf %d 0x$DefsDay`" DefsYear="`echo "z$Line" | awk '{print $5$4}'`" DefsYear="`printf %d 0x$DefsYear`" break else DefsMonth="" break fi done # If file type was not correct, return 1 [ -z "$DefsMonth" ] && return 1 case $DefsMonth in 1) DefsMonthName=January ;; 2) DefsMonthName=February ;; 3) DefsMonthName=March ;; 4) DefsMonthName=April ;; 5) DefsMonthName=May ;; 6) DefsMonthName=June ;; 7) DefsMonthName=July ;; 8) DefsMonthName=August ;; 9) DefsMonthName=September ;; 10) DefsMonthName=October ;; 11) DefsMonthName=November ;; 12) DefsMonthName=December ;; esac DefsFolder=`dirname "$FilePassed"` TempOtoolFile="/tmp/GetDatesDate-otool-`date +"%Y%m%d%H%M%S"`.plist" otool -s __TEXT __info_plist "$DefsFolder/navlibx" 2>/dev/null | xxd -r - "$TempOtoolFile" 2>/dev/null navlibxVersion=`cat -v "$TempOtoolFile" 2>/dev/null | grep CFBundleShortVersionString -A1 | tail -n 1 | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` rm -f "$TempOtoolFile" 2>/dev/null DefsDate="$DefsMonthName $DefsDay, $DefsYear (build $DefsBuild)`[ "$navlibxVersion" ] && echo " (navlibx $navlibxVersion)"`" return 0 } ShowDefsDateForFileOrFolder() { # Usage: ShowDefsDateForFileOrFolder $1 # Argument: $1 = Name of file or folder to check # Summary: Shows virus defs date for file or folder passed. # local CurrentDir=`pwd` local DefsDate="" local FileToCheck if [ -d "$1" -a $ShowIndividualFiles = false ] ; then cd "$1" for FileToCheck in `ls 2>/dev/null | grep -ie 'virscan[0-9]'` ; do GetDefsDate "$FileToCheck" # If DefsDate was assigned, break [ -n "$DefsDate" ] && break done if [ -n "$DefsDate" ] ; then echo "Date of virus defs in folder '$1':" echo " $DefsDate" else echo "No virus defs date was found in any file within folder: $1" fi echo elif [ -d "$1" -a $ShowIndividualFiles = true ] ; then cd "$1" for FileToCheck in `ls` ; do GetDefsDate "$FileToCheck" if [ -n "$DefsDate" ] ; then echo "Date of virus defs file '$1/$FileToCheck':" echo " $DefsDate" echo else # If filename does not begin with a period (is not invisible) if [ "`basename "$FileToCheck" | awk '{print substr($0,1,1)}'`" != "." ] ; then echo "No virus defs date was found in file: $1/$FileToCheck" echo fi fi done elif [ -f "$1" ] ; then GetDefsDate "$1" if [ -n "$DefsDate" ] ; then echo "Date of virus defs file '$1':" echo " $DefsDate" else echo "No virus defs date was found in file: $1" fi echo else echo "No such file or folder: '$1'" echo fi cd "$CurrentDir" } AntiVirusDirs="$AntiVirusDirOld" [ ! -d "$AntiVirusDirs" ] && AntiVirusDirs="$AntiVirusDir2" [ ! -d "$AntiVirusDirs" ] && AntiVirusDirs="$AntiVirusDirs6" echo if [ -z "$AntiVirusDirs" ] ; then echo "NOTE: Could not find any installed AntiVirus definitions." echo return fi RemainingDirsToCheck=`echo "$AntiVirusDirs" | grep -c .` IFS=$'\n' for AntiVirusDir in $AntiVirusDirs ; do (( RemainingDirsToCheck-- )) cd "$AntiVirusDir" 2>/dev/null if [ $? = 0 ] ; then echo "AntiVirus definitions in:" echo " \"$AntiVirusDir\"" echo DefsFolderWereFound=false for EachInstalledFolder in `ls -d [0-9][0-9][0-9][0-9]* Engine [Hh]ub NewEngine SavedEngine 2>/dev/null | sort -f` ; do DefsFolderWereFound=true ShowDefsDateForFileOrFolder "$EachInstalledFolder" done $DefsFolderWereFound || printf "No definitions were found in that folder.\n\n" fi if [ $RemainingDirsToCheck -gt 0 ] ; then echo "-----" echo fi done IFS="$SavedIFS" } ShowInstalledWCIDSignaturesDates() { local DefsDirName="WebFraud" local DefsDir="/Library/Application Support/Symantec/$DefsDirName" local DefsDir6="/Library/Application Support/Symantec/Silo/NFM/Definitions/symcdata/webprotectiondefs" local FileToCheck="virscan1.dat" local HubDir="$DefsDir/Hub" local HubDir6Name="binhub" local SavedIFS="$IFS" local ShowIndividualFiles=false GetDefsDate() { # Usage: GetDefsDate $1 # Argument: $1 = File from which to get date. # Summary: Gets the date from a file if it is a WCID def file. # Assigns date to DefsDate variable and returns 0 if # a date is found, else assigns NULL to DefsDate and # returns 1. # local DefsBuild local DefsDay local DefsItemSeq local DefsMonth="" local DefsMonthName local DefsYear local Signature DefsDate="" # If $1 is not a file, return 1 test -f "$1" || return 1 # If $1 has a filename that begins with a period, return 1 test "`basename "$1" | awk '{print substr($0,1,1)}'`" = "." && return 1 Line=`hexdump -C -v -n 16 "$1" | head -n 1` # If Signature is not SYMC, return 1 Signature=`echo "z$Line" | awk '{print $2$3$4$5}'` [ "z$Signature" != z53594d43 ] && return 1 DefsMonth=`echo "z$Line" | awk '{print $10}'` DefsMonth=`printf %d 0x$DefsMonth` DefsDay=`echo "z$Line" | awk '{print $11}'` DefsDay=`printf %d 0x$DefsDay` DefsYear=`echo "z$Line" | awk '{print $12}'` DefsYear=`printf %d 0x$DefsYear` DefsYear=`expr $DefsYear + 1900` DefsBuild=`echo "z$Line" | awk '{print $9$8$7$6}'` DefsBuild=`printf %d 0x$DefsBuild` # If file type was not correct, return 1 [ -z "$DefsMonth" ] && return 1 case $DefsMonth in 1) DefsMonthName=January ;; 2) DefsMonthName=February ;; 3) DefsMonthName=March ;; 4) DefsMonthName=April ;; 5) DefsMonthName=May ;; 6) DefsMonthName=June ;; 7) DefsMonthName=July ;; 8) DefsMonthName=August ;; 9) DefsMonthName=September ;; 10) DefsMonthName=October ;; 11) DefsMonthName=November ;; 12) DefsMonthName=December ;; esac DefsItemSeq=`expr $DefsYear - 2000``printf %.2d%.2d%.3d $DefsMonth $DefsDay $DefsBuild` DefsDate="$DefsMonthName $DefsDay, $DefsYear - build $DefsBuild ($DefsItemSeq)" return 0 } ShowDefsDateForFileOrFolder() { # Usage: ShowDefsDateForFileOrFolder $1 # Argument: $1 = Name of file or folder to check # Summary: Shows WCID defs date for file or folder passed. # local CurrentDir=`pwd` local DefsDate="" local FileToCheck if [ -d "$1" -a $ShowIndividualFiles = false ] ; then cd "$1" for FileToCheck in `ls` ; do GetDefsDate "$FileToCheck" # If DefsDate was assigned, break test -n "$DefsDate" && break done if [ -n "$DefsDate" ] ; then echo "Date of WCID defs in folder '$1':" echo " $DefsDate" else echo "No WCID defs date was found in any file within folder: $1" fi echo elif [ -d "$1" -a $ShowIndividualFiles = true ] ; then cd "$1" for FileToCheck in `ls` ; do GetDefsDate "$FileToCheck" if [ -n "$DefsDate" ] ; then echo "Date of WCID defs file '$1/$FileToCheck':" echo " $DefsDate" echo else # If filename does not begin with a period (is not invisible) if [ "`basename "$FileToCheck" | awk '{print substr($0,1,1)}'`" != "." ] ; then echo "No WCID defs date was found in file: $1/$FileToCheck" echo fi fi done elif [ -f "$1" ] ; then GetDefsDate "$1" if [ -n "$DefsDate" ] ; then echo "Date of WCID defs file '$1':" echo " $DefsDate" else echo "No WCID defs date was found in file: $1" fi echo else echo "No such file or folder: '$1'" echo fi cd "$CurrentDir" } IFS=$'\n' cd "$DefsDir" 2>/dev/null if [ $? = 0 ] ; then cd .. ShowDefsDateForFileOrFolder "$DefsDirName" ShowDefsDateForFileOrFolder "$DefsDirName/Hub" elif [ -d "$DefsDir6" ] ; then cd "$DefsDir6" for Folder in `ls -d 2* "$HubDir6Name" 2>/dev/null` ; do ShowDefsDateForFileOrFolder "$Folder" done IFS="$SavedIFS" else echo "Could not find any installed anti-phishing (WCID) definitions." echo fi } ShowLoginWindowPlists() { local EachUserDirDir local PLISTFILE IFS=' ' for EachUserDir in $ComputerUsersHomeDirsAndRootDir ; do if [ "z$EachUserDir" = z/ ] ; then PLISTFILE=/Library/Preferences/loginwindow.plist else PLISTFILE="$EachUserDir/Library/Preferences/loginwindow.plist" fi [ ! -f "$PLISTFILE" ] && continue cp "$PLISTFILE" "$TempFile" plutil -convert xml1 "$TempFile" 2>/dev/null 1>&2 if [ $? != 0 ] ; then echo "$PLISTFILE" echo echo "ERROR: File could not be converted by plutil. Perhaps it is damaged." echo continue elif [ -n "`diff "$PLISTFILE" "$TempFile" 2>/dev/null`" ] ; then echo "$PLISTFILE (binary file)" else echo "$PLISTFILE" fi echo tr '\015' '\012' < "$TempFile" | cat -v | grep -v '^<' echo done } ShowPlistContents() { # Usage: ShowPlistContents file # Summary: Shows contents of plist file. # local TempFile="$TempFolder/temp-ShowPlistContents.txt" cp -f "$1" "$TempFile" plutil -convert xml1 "$TempFile" &>/dev/null [ $? = 0 ] && cat "$TempFile" } ShowProgramAndOSinfo() { # Usage: ShowProgramAndOSinfo # Summary: Shows script version, date, OS, and architecture # local RootlessStatus= VolumePlist="/System/Library/CoreServices/SystemVersion.plist" if [ ! -f "$VolumePlist" ] ; then VersionOfOS="N/A" else VersionOfOS=`grep -A1 "ProductVersion" "$VolumePlist" 2>/dev/null | tail -n 1 | grep '10\.' | tr -d "<[:alpha:]>/" | awk '{print $1}'` [ -z "$VersionOfOS" ] && VersionOfOS="N/A" fi if [ "`arch | grep -i ppc`" ] ; then Arch=PPC else Arch=Intel fi if [ "`uname -m | grep -e '_64$'`" ] ; then Bit=64-bit else Bit=32-bit fi HardwareUUID=`/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice 2>/dev/null | grep IOPlatformUUID | awk -F '"' '{print $4}'` [ -z "$HardwareUUID" ] && HardwareUUID="could not be determined" echo " $PartialScriptName $Version - ran `$RunWithSupportFolder && echo "with" || echo "without"` support folder from: \"$ScriptDir\" `date` OS $VersionOfOS ($Arch $Bit) Hardware UUID: $HardwareUUID " RootlessStatus=`csrutil status 2>/dev/null` if [ "$RootlessStatus" ] ; then echo "$RootlessStatus " fi } ShowUsage() { # Usage: ShowUsage [$1 [$2]] # Arguments: $1 = Exit code. # $2 = Error message to display before showing usage. # Summary: Displays script usage. If an exit code is passed, # script is exited with that value. # if [ "$2" ] ; then echo echo "$2" echo fi ShowHelp | grep "^Usage.*:" [ "$2" ] && echo [ -n "$1" ] && exit "$1" } YorN() { # Usage: YorN [-e] [-n] [-q] [Default] String # Version: 1.0.2 # Arguments: -e - Use echochar program to get input. ScriptDir must be # defined, echochar must be executable, and ScriptDir # must be within or next to LiveUpdateTools folder. # Note that keyboard must be used for echochar input, # so piped standard input and ctrl-C are not usable. # The echochar program was written by Bill Allen. # -n - Don't print a blank line after entry. # -q - Add q for quit option. # Default - n, false, y, true. If not one of those, no # default is used. # String - The question to ask, without a question mark. # Summary: Prompts with String + "? (y/n) " + "[n] " or "[y] " or "", # depending on Default passed. Prompt is repeated until y or # n is entered, or until "" is entered if Default is n or y. # A blank line is printed after y or n is entered unless -n # is specified. # Returns 0 if y is entered, 1 if n is entered, 2 if q is # entered and -q was passed to YorN. # History: 1.0.0 - Added Intel-only version of echochar for OS 10.5 # and later; prior OS versions use old PPC version. # 1.0.1 - Added arch check so that PPC version is used on PPC. # 1.0.2 - Changed carriage return value to "`printf "\r"`". # local YNAdditionalText="" local YNArgCount=$# local YNDefaultAnswer="" local YNDefaultAnswerString="" local YNDoPrintBlank=true local YNechochar="" local YNResponse="" local YNTextToShow="" while [ $YNArgCount -gt 0 ] ; do if [ "z$1" = z-e ] ; then YNechochar="$ScriptDir/LiveUpdateTools/CharTools/echochar" [ ! -x "$YNechochar" ] && YNechochar="$ScriptDir/CharTools/echochar" [ ! -x "$YNechochar" ] && YNechochar="$ScriptDir/../CharTools/echochar" [ ! -x "$YNechochar" ] && YNechochar="$ScriptDir/../../CharTools/echochar" [ ! -x "$YNechochar" ] && YNechochar="$ScriptDir/../../../CharTools/echochar" [ ! -x "$YNechochar" ] && YNechochar="$ScriptDir/../../../../CharTools/echochar" [ ! -x "$YNechochar" ] && YNechochar="$ScriptDir/../../../../../CharTools/echochar" if [ -z "$OSXmajorVersion" ] ; then OSXmajorVersion=`grep -A1 "ProductVersion" /System/Library/CoreServices/SystemVersion.plist 2>/dev/null | tail -n 1 | grep '10\.' | tr -d "<[:alpha:]>/" | awk -F . '{print $2}'` [ "$OSXmajorVersion" ] && OSXmajorVersion=`expr $OSXmajorVersion - 0 2>/dev/null` [ -z "$OSXmajorVersion" ] && OSXmajorVersion=0 fi [ $OSXmajorVersion -lt 5 -o -n "`arch 2>/dev/null | grep -i ppc`" ] && YNechochar="$YNechochar"-ppc elif [ "z$1" = z-n ] ; then YNDoPrintBlank=false elif [ "z$1" = z-q ] ; then YNAdditionalText=/q elif [ "z$1" = zn -o "z$1" = zfalse ] ; then YNDefaultAnswer=n YNDefaultAnswerString="[n] " elif [ "z$1" = zy -o "z$1" = ztrue ] ; then YNDefaultAnswer=y YNDefaultAnswerString="[y] " else YNTextToShow="$1" fi shift let YNArgCount=$YNArgCount-1 done [ "$2" ] && YNTextToShow="$2" while [ : ] ; do printf "%s? (y/n$YNAdditionalText) %s" "$YNTextToShow" "$YNDefaultAnswerString" if [ -x "$YNechochar" ] ; then YNResponse=`"$YNechochar"` echo "$YNResponse" # If response was a carriage return, make it NULL [ "$YNResponse" = "`printf "\r"`" ] && YNResponse="" else read YNResponse fi if [ "$YNResponse" ] ; then YNResponse=`printf "%s" "$YNResponse" | awk '{print tolower($0)}'` else YNResponse="$YNDefaultAnswer" fi if [ "z$YNResponse" = zn ] ; then $YNDoPrintBlank && echo return 1 elif [ "z$YNResponse" = zq -a -n "$YNAdditionalText" ] ; then $YNDoPrintBlank && echo return 2 elif [ "z$YNResponse" = zy ] ; then $YNDoPrintBlank && echo return 0 fi done } # *** Beginning of Commands to Execute *** ScriptPath=`ShowFullFilePath "$0" -P` [ ! -e "$ScriptPath" ] && ExitScript 99 "WARNING: ScriptPath definition failed. Script aborted." FullScriptName=`basename "$ScriptPath"` PartialScriptName=`basename "$FullScriptName" .command` ScriptDir=`dirname "$ScriptPath"` ScriptSupportDir="$ScriptDir/$ScriptSupportDirName" TempFolder=/private/tmp/$PartialScriptName-`date +"%Y%m%d%H%M%S"` TempBody=$TempFolder/body.txt TempFile=$TempFolder/temp.txt TempHeader=$TempFolder/header.txt TempSymantecInfoFolder=$TempFolder/$InfoOutputBase if [ -d "$ScriptSupportDir" ] ; then RunWithSupportFolder=true else RunWithSupportFolder=false fi AssignSymantecSupportFolderVariables ProcessArguments --OptionTakesUnparsedArgument=-a --OptionTakesUnparsedArgument=-z "$@" if [ ! -f "$ZIP" ] ; then if $RunWithSupportFolder ; then ZIP="$ScriptSupportDir/zip" else ExitScript 2 "WARNING: Could not find zip program. Quitting." fi fi if [ $# -eq 0 ] ; then # If no arguments were passed to script # Run script as if it was double-clicked in Finder so that # screen will be cleared and quit message will be displayed. RunScriptAsStandAlone=true else # Run script in command line mode so that # screen won't be cleared and quit message won't be displayed. RunScriptAsStandAlone=false fi $RunScriptAsStandAlone && clear DefineCurrentUserDesktopAndOS $OptionForDefineCurrentUserDesktopAndOS GetFileInfoProgram="$ScriptSupportDir/GetFileInfo" [ $OSXmajorVersion -lt 5 ] && GetFileInfoProgram="$ScriptSupportDir/GetFileInfo-ppc" if [ "`whoami`" != root ] ; then if $PublicVersion ; then GetAdminPassword true # Prompt user for admin password fi # Run this script again as root sudo -p "Please enter your admin password: " "$0" "$@" ErrorFromSudoCommand=$? # If unable to authenticate if [ $ErrorFromSudoCommand -eq 1 ] ; then echo "You entered an invalid password or you are not an admin user. Script aborted." ExitScript 1 fi if $PublicVersion ; then sudo -k # Make sudo require a password the next time it is run fi rm -rf "$TempFolder" 2>/dev/null exit $ErrorFromSudoCommand # Exit so script doesn't run again fi IFS=$'\n' # Set IFS to newlines GetComputerUsers if $RunWithSupportFolder ; then # Set permissions chmod -R a+x "$ScriptSupportDir" "$ScriptDir/$FullScriptName" 2>/dev/null chmod a-x "$ScriptSupportDir/"*.txt 2>/dev/null fi if $DoCreateZipArchive ; then [ ! -f "$ZIP" -o ! -x "$ZIP" ] && ExitScript 3 "WARNING: Could not find valid zip program." fi # Get LiveUpdate 5 subscription key - this is no longer done as of GatherSymantecInfo.command 2.0.0 if $DoPromptForKey ; then printf " Please enter the subscription key you are trying to use (e.g., ND655D64A96) (if you don't have a subscription key, simply press return): " read KeyUsed if ! $ShowUnlimitedLinesInLogs ; then echo YorN n -n "Show all lines in logs (doing so may make the report very large)" [ $? = 0 ] && ShowUnlimitedLinesInLogs=true fi else KeyUsed="" fi [ -z "$KeyUsed" ] && KeyUsed=N/A # Generate temporary report header and body echo " Gathering information... " ItemNumber=1 mkdir -p "$TempSymantecInfoFolder" 2>/dev/null ShowProgramAndOSinfo >"$TempHeader" [ ! -d "$TempSymantecInfoFolder" ] && ExitScript 2 "WARNING: Could not create temporary folder. Program aborted." chmod -R 777 "$TempFolder" 2>/dev/null echo "The following information is shown in this report: " >>"$TempHeader" echo "" >"$TempBody" # --- Add to report: Symantec product info ECHOL -a "Installed Symantec product info" if $RunWithSupportFolder ; then "$ScriptSupportDir/$NortonAppInfoProgram" -a -c >>"$TempBody" else ShowInstalledApplicationInfo >>"$TempBody" fi # --- Add to report: Symantec content info ECHOL -a "Symantec content info" ShowInstalledVirusDefsDates >>"$TempBody" echo "-----" >>"$TempBody" echo "" >>"$TempBody" ShowInstalledIPSSignaturesDates >>"$TempBody" echo "-----" >>"$TempBody" echo "" >>"$TempBody" ShowInstalledWCIDSignaturesDates >>"$TempBody" if [ -f "$ScriptSupportDir/navmanout" -a -x "$ScriptSupportDir/navmanout" ] ; then # --- Add to report: NAV 12 engine.mfst ECHOL -a "NAV 12 virus definitions manifest (engine.mfst)" ManifestOutput=`"$ScriptSupportDir/navmanout" 2>/dev/null` # If navmanout returned error, add a blank line [ $? != 0 ] && echo "" >>"$TempBody" [ "$ManifestOutput" ] && echo "$ManifestOutput" >>"$TempBody" fi # If NIS 6/NFM 7 is installed if [ -d "$SiloRootDir" ] ; then ECHOL "NIS 6 and later definitions' libecomlodr.dylib, definfo.dat and usage.dat files" # If libecomlodr.dylib does not exist in /usr/local/lib if [ ! -e /usr/local/lib/libecomlodr.dylib ] ; then echo "WARNING: Not found: /usr/local/lib/libecomlodr.dylib" >>"$TempBody" else CodesignOutput=`codesign --display --verbose=4 /usr/local/lib/libecomlodr.dylib 2>&1` # If libecomlodr.dylib has a signature error if [ $? != 0 ] ; then echo "WARNING: Signature error was found for /usr/local/lib/libecomlodr.dylib:" >>"$TempBody" echo "" >>"$TempBody" echo "$CodesignOutput" >>"$TempBody" # Else if it signed by Symantec elif [ "`echo "$CodesignOutput" | egrep -e "^Authority=Symantec Corporation|^Authority=Developer ID Application: Symantec"`" ] ; then echo "NOTE: Verified that the codesign signature was created by Symantec for:" >>"$TempBody" echo " /usr/local/lib/libecomlodr.dylib" >>"$TempBody" else echo "WARNING: Signature for /usr/local/lib/libecomlodr.dylib was not created by Symantec." >>"$TempBody" fi fi echo "" >>"$TempBody" # Find definitions' definfo.dat and usage.dat files NIS6ContentDatFiles="" for EachDefsDir in $DefinitionsInSiloDirs ; do NIS6ContentDatFiles="$NIS6ContentDatFiles `find "$EachDefsDir" -iname '*.dat' 2>/dev/null | grep -iEe '/definfo.dat$|/usage.dat$'`" done NIS6ContentDatFiles=`echo "$NIS6ContentDatFiles" | grep .` if [ "$NIS6ContentDatFiles" ] ; then CatFilesInList -l "$NIS6ContentDatFiles" else echo "No definfo.dat or usage.dat files were found." >>"$TempBody" fi fi # --- Add to report: SymSharedSettingsd version ECHOL "/Library/PrivateFrameworks/SymSharedSettings.framework/Tools/SymSharedSettingsd -V" if [ -f /Library/PrivateFrameworks/SymSharedSettings.framework/Tools/SymSharedSettingsd ] ; then /Library/PrivateFrameworks/SymSharedSettings.framework/Tools/SymSharedSettingsd -V 2>>"$TempBody" 1>>"$TempBody" else echo "SymSharedSettingsd does not exist." >>"$TempBody" fi # --- Add to report: Versions of applications in /Applications ECHOL "Application versions (CFBundleShortVersionString) in /Applications" for App in `find /Applications -iname '*.app' -maxdepth 2 | sort -f` ; do CFBundleShortVersionString=`defaults read "$App/Contents/Info" CFBundleShortVersionString 2>/dev/null` if [ "$CFBundleShortVersionString" ] ; then SubFolderName=`echo "$App" | awk -F / '{print $3}'` # If app is loose in /Applications if [ "`printf "%s" "$SubFolderName" | grep -ie '\.app$'`" ] ; then StringToAdd="" else StringToAdd="$SubFolderName: " fi echo " $StringToAdd`basename "$App" .app` - $CFBundleShortVersionString" >>"$TempBody" fi done # --- Add to report: Symantec processes ECHOL "Symantec processes currently running" PSoutput=`ps aux -ww | grep -i "LiveUpdateAdminUtility\|/Application Support/Norton\|/Application Support/Symantec\|/Applications/Norton\|/Applications/Symantec\|PrivateFrameworks/NPF\|PrivateFrameworks/Sym\|/StartupItems/.*Norton\|/StartupItems/NUMCompatibilityCheck\|/StartupItems/SMac Client\|/StartupItems/Sym\|/StartupItems/TrackDelete\|/StartupItems/VolumeAssist" | grep -v " grep -"` if [ "$PSoutput" ] ; then ps aux -ww | head -n 1 >>"$TempBody" echo "$PSoutput" >>"$TempBody" fi # --- Add to report: kexts ECHOL "Symantec kexts currently loaded" kextstat 2>/dev/null 1>&2 if [ $? -gt 0 ] ; then kmodstat | grep -i Symantec | grep -v " grep -" >>"$TempBody" else kextstat | grep -i Symantec | grep -v " grep -" >>"$TempBody" fi # --- Add to report: All processes ECHOL "All processes currently running" ps aux -ww >>"$TempBody" # --- Add to report: locale information ECHOL "Locale information" echo "defaults read NSGlobalDomain AppleLanguages" >>"$TempBody" defaults read NSGlobalDomain AppleLanguages 2>>"$TempBody" 1>>"$TempBody" # --- Add to report: user home folders info ECHOL "User home folders information" echo "Table of computer user home folders:" >>"$TempBody" echo "" >>"$TempBody" echo "$ComputerUsersTable" >>"$TempBody" echo "" >>"$TempBody" echo "Items in /Users:" >>"$TempBody" echo "" >>"$TempBody" # Output of ls /Users without total, ., and .. lines ls -lT /Users 2>/dev/null | sort -f -k10 | egrep -v '^[Tt]otal| \.$| \.\.$' >>"$TempBody" # --- Add to report: Definitions avdefs group check ECHOL "Definitions avdefs group check" dseditgroup -o read avdefs &>/dev/null if [ $? = 0 ] ; then echo "avdefs group exists" >>"$TempBody" else echo "WARNING: avdefs group does not exist" >>"$TempBody" fi echo "" >>"$TempBody" if [ -f "/etc/symantec/defutils.conf" -o -n "$DefinitionsInSiloDirs" ] ; then DefsFilesToCheck="/etc/symantec/defutils.conf" for DirToCheck in $DefinitionsInSiloDirs ; do DefsFilesToCheck="$DefsFilesToCheck `find "$DirToCheck" 2>/dev/null`" done DefsPathsWithWrongGroup="" for DefsPath in $DefsFilesToCheck ; do lsOutput=`ls -ld "$DefsPath" 2>/dev/null` if [ "`printf "%s" "$lsOutput" | awk '{print $4}'`" != "avdefs" ] ; then DefsPathsWithWrongGroup="$DefsPathsWithWrongGroup $lsOutput" fi done if [ "$DefsPathsWithWrongGroup" ] ; then echo "WARNING: The following should have group set to avdefs:" >>"$TempBody" echo "$DefsPathsWithWrongGroup" >>"$TempBody" else echo "All definitions files have expected group (avdefs)." >>"$TempBody" fi else echo "No NFM definitions files were found." >>"$TempBody" fi # --- Add to report: VerifySignedFiles - Apple signing verification if [ $RunWithSupportFolder = true -a $DoRunVerifySignedFiles = true -a -f "$ScriptSupportDir/VerifySignedFiles/VerifySignedFiles.command" -a $OSXmajorVersion -gt 4 ] ; then ECHOL -a "VerifySignedFiles - Apple signing verification" echo "Running VerifySignedFiles to check Apple signing..." echo "$ScriptSupportDir/VerifySignedFiles/VerifySignedFiles.command" -a -r >>"$TempBody" echo "Gathering more information..." echo fi # --- Add to report: Symantec error reporting info ECHOL "Symantec Error Reporting" CatFilesInList /Library/Preferences/com.symantec.errorreporting.plist for UserDir in $ComputerUsersHomeDirsAndRootDir ; do [ "z$UserDir" = "z/" ] && UserDir="" if [ -d "$UserDir$ErrorReportingSubmissionsFolder" ] ; then echo "Reports in \"$UserDir$ErrorReportingSubmissionsFolder\"" >>"$TempBody" echo "" >>"$TempBody" CatFilesInList -R "$UserDir$ErrorReportingSubmissionsFolder" xml fi if [ -d "$UserDir$ErrorReportingSubmissionsInNFMSiloFolder" ] ; then echo "Reports in \"$UserDir$ErrorReportingSubmissionsInNFMSiloFolder\"" >>"$TempBody" echo "" >>"$TempBody" CatFilesInList -R "$UserDir$ErrorReportingSubmissionsInNFMSiloFolder" xml fi done # --- Add to report: Symantec Info.plist files ECHOL "Contents of Symantec Info.plist files" ItemsToSearch=" `ls -d /Applications/Norton* 2>/dev/null` `ls -d /Applications/Symantec* 2>/dev/null` `ls -d "/Library/Application Support/Symantec"* 2>/dev/null` `ls -d "/Library/Extensions/Norton"* 2>/dev/null` `ls -d "/Library/Extensions/Sym"* 2>/dev/null` `ls -d "/Library/PrivateFrameworks/Sym"* 2>/dev/null` `ls -d "/System/Library/Extensions/Norton"* 2>/dev/null` `ls -d "/System/Library/Extensions/Sym"* 2>/dev/null`" for EachLine in $ItemsToSearch ; do [ -L "$EachLine" -o ! -d "$EachLine" ] && continue CatFilesInList -q -v '\.storyboardc/' -R "$EachLine" "/Info.plist" done # --- Add to report: listing of Symantec support files ECHOL "Files in Symantec's support folders" ls -dlT "/Library/Application Support/Norton Solutions Support" 2>>"$TempBody" 1>>"$TempBody" if [ -e "/Library/Application Support/Norton Solutions Support" ] ; then ls -RlT "/Library/Application Support/Norton Solutions Support" >>"$TempBody" fi echo "" >>"$TempBody" ls -dlT "$SymantecSupportDir" 2>>"$TempBody" 1>>"$TempBody" if [ -e "$SymantecSupportDir" ] ; then ls -RlT "$SymantecSupportDir" >>"$TempBody" fi # --- Add to report: expected links in / ECHOL "Expected links in /" ls -ldT /etc /tmp /var 2>>"$TempBody" 1>>"$TempBody" if [ ! -L /etc ] ; then echo "" >>"$TempBody" echo "WARNING: /etc should be a link to private/etc" >>"$TempBody" if [ -d /etc ] ; then echo " Files in /etc folder:" >>"$TempBody" echo "" >>"$TempBody" ls -lT /etc/ 2>/dev/null | sort -f -k10 1>>"$TempBody" fi fi if [ ! -L /tmp ] ; then echo "" >>"$TempBody" echo "WARNING: /tmp should be a link to private/tmp" >>"$TempBody" if [ -d /tmp ] ; then echo " Files in /tmp folder:" >>"$TempBody" echo "" >>"$TempBody" ls -lT /tmp/ 2>/dev/null | sort -f -k10 1>>"$TempBody" fi fi if [ ! -L /var ] ; then echo "" >>"$TempBody" echo "WARNING: /var should be a link to private/var" >>"$TempBody" if [ -d /var ] ; then echo " Files in /var folder:" >>"$TempBody" echo "" >>"$TempBody" ls -lT /var/ 2>/dev/null | sort -f -k10 1>>"$TempBody" fi if [ -d /var/tmp ] ; then echo "" >>"$TempBody" echo "WARNING: /var should be a link to private/var" >>"$TempBody" echo " Files in /var/tmp folder:" >>"$TempBody" echo "" >>"$TempBody" ls -lT /var/tmp/ 2>/dev/null | sort -f -k10 1>>"$TempBody" fi fi # --- Add to report: items in / ECHOL "Items in /" ls -lT / 2>/dev/null | sort -f -k10 1>>"$TempBody" # --- Add to report: permissions of /usr/local folders ECHOL "Permissions of /usr/local folders" ls -ldT /usr/local /usr/local/bin /usr/local/lib 2>>"$TempBody" 1>>"$TempBody" # --- Add to report: files in /private/tmp ECHOL "Files in /private/tmp" ls -lT /private/tmp 2>/dev/null | sort -f -k10 1>>"$TempBody" # --- Add to report: files in /private/var/tmp ECHOL "Files in /private/var/tmp" ls -lT /private/var/tmp 2>/dev/null | sort -f -k10 1>>"$TempBody" # --- Add to report: liveupdate.conf ECHOL "Contents of /private/etc/liveupdate.conf" if [ -f /private/etc/liveupdate.conf ] ; then cat /private/etc/liveupdate.conf >>"$TempBody" else echo "File does not exist." >>"$TempBody" fi # --- Add to report: LiveUpdate date file info ECHOL -a "LiveUpdate date file info" DateFiles="" for UserDir in $ComputerUsersHomeDirsAndRootDir ; do [ "$UserDir" = / ] && UserDir="" [ -f "$UserDir$LUDateFile" ] && DateFiles="$DateFiles $UserDir$LUDateFile" done if [ "$DateFiles" ] ; then for EachFile in $DateFiles ; do echo "" >>"$TempBody" ls -lT "$EachFile" >>"$TempBody" echo "" >>"$TempBody" cp -f "$EachFile" "$TempFile" plutil -convert xml1 "$TempFile" 2>/dev/null 1>&2 [ $? = 0 ] && cat "$TempFile" >>"$TempBody" done else echo " Could not find $LUDateFile or date file for any user." >>"$TempBody" fi if $RunWithSupportFolder ; then # --- Add to report: Subscription info (LiveUpdate 5 and earlier) ECHOL "Subscription info (LiveUpdate 5 and earlier)" # Key is no longer retrieved as of GatherSymantecInfo.command 2.0.0 # echo "Subscription Key used by customer: $KeyUsed" >>"$TempBody" # If Mac OS version is less than 10.5 or running on a PPC if [ $OSXmajorVersion -lt 5 -o -n "`arch | grep -i ppc`" ] ; then # Check LiveUpdate 3-4 subscriptions echo " Norton AntiVirus Subscription Info (LiveUpdate 3-4)" >>"$TempBody" "$ScriptSupportDir/$NAVSubInfoProgram" 2>"$TempFile" 1>&2 cat "$TempFile" >>"$TempBody" echo " Norton Internet Security Subscription Info (LiveUpdate 3-4)" >>"$TempBody" "$ScriptSupportDir/$NISSubInfoProgram" 2>"$TempFile" 1>&2 cat "$TempFile" >>"$TempBody" echo "" >>"$TempBody" fi echo "LiveUpdate 5 Subscription Info" >>"$TempBody" echo "" >>"$TempBody" if [ -f "$KeychainFile" ] ; then # If NIS 4 or earlier is installed if [ -d "$LiveUpdateSupportDirNIS4" ] ; then # Obtain subscription info [ ! -f "$IRToolProgram" ] && IRToolProgram="$ScriptSupportDir/IRSpecial" if [ -f "$IRToolProgram" ] ; then "$IRToolProgram" -printout 2>"$TempFile" 1>&2 cat "$TempFile" >>"$TempBody" fi fi echo "" >>"$TempBody" if [ -f "$GetFileInfoProgram" ] ; then "$GetFileInfoProgram" "$KeychainFile" 2>"$TempFile" 1>&2 else ls -lT "$KeychainFile" 2>"$TempFile" 1>&2 fi cat "$TempFile" >>"$TempBody" fi fi ECHOL "Keychain Info" if [ -e "$KeychainFileLocation" ] ; then ls -ldT "$KeychainFileLocation" "$KeychainFileLocation/"* 2>/dev/null | sort -f -k10 1>>"$TempBody" 2>/dev/null else echo " Keychain not found." >>"$TempBody" fi # --- Add to report: Corporate files ECHOL "Corporate files in /Users/Shared" Text=`ls -ldT /Users/Shared/* 2>/dev/null | grep Corporate` [ -z "$Text" ] && Text="None found." echo "$Text" >>"$TempBody" # --- Add to report: LaunchAgents plists ECHOL "Contents of plist files in /Library/LaunchAgents" CatFilesInList /Library/LaunchAgents/ # --- Add to report: LaunchDaemons plists ECHOL "Contents of plist files in /Library/LaunchDaemons" CatFilesInList /Library/LaunchDaemons/ # --- Add to report: loginwindow.plist files ECHOL "Contents of loginwindow.plist files" ShowLoginWindowPlists >>"$TempBody" # --- Add to report: crontabs ECHOL -a "Crontab entries" ShowCrontabEntries >>"$TempBody" if $RunWithSupportFolder ; then # --- Add to report: shut down times ECHOL "Shut down times as reported by PrintShutDownTimes" if [ $OSXmajorVersion -lt 5 ] ; then echo "Must be running OS 10.5 or later to run PrintShutDownTimes." >>"$TempBody" else "$ScriptSupportDir/PrintShutDownTimes" 2>>"$TempBody" 1>>"$TempBody" fi fi # --- Add to report: proxy info ECHOL "Proxy info via system_profiler" if [ $OSXmajorVersion -lt 4 ] ; then echo "Must be running OS 10.4 or later to see this info." >>"$TempBody" else system_profiler SPNetworkDataType 2>/dev/null | grep -i proxy >>"$TempBody" fi # --- Add to report: Apple System Profile without user sensitive data ECHOL "system_profiler -detailLevel mini | grep -iv 'serial num\|part num'" if [ $OSXmajorVersion -lt 4 ] ; then echo "Must be running OS 10.4 or later to see this info." >>"$TempBody" else system_profiler -detailLevel mini 2>/dev/null | grep -iv 'serial num\|part num' >>"$TempBody" fi # --- Add to report: Symantec daemon logs ECHOL "`$ShowUnlimitedLinesInLogs && echo Entire || echo "Last $LinesToShowInDaemonErrorLog lines of"` SymDaemon logs" CatFilesInList -N -n $LinesToShowInDaemonErrorLog -l "$SymDaemonLogs" # --- Add to report: SymDaemon sampling ECHOL "Sampling of SymDaemon" SymDaemonSampleWasTaken=false SymDaemonProcessIDs=`ps aux -ww | grep SymDaemon | grep -v grep | awk '{print $2}'` for SymDaemonProcessID in $SymDaemonProcessIDs ; do $SymDaemonSampleWasTaken && echo "" >>"$TempBody" echo "Obtaining sampling of SymDaemon (process ID $SymDaemonProcessID)" sample "$SymDaemonProcessID" -mayDie -file "$TempFile" &>/dev/null SymDaemonSampleWasTaken=true echo "--- Sampling of SymDaemon (process ID $SymDaemonProcessID) ---" >>"$TempBody" echo "" >>"$TempBody" cat "$TempFile" >>"$TempBody" done $SymDaemonSampleWasTaken && echo [ -z "$SymDaemonProcessIDs" ] && echo "No SymDaemon processes were found." >>"$TempBody" # --- Add to report: licensing logs ECHOL "Licensing logs in $SymantecSupportDir/Licensing" CatFilesInList -R "$SymantecSupportDir/Licensing" log ECHOL "Licensing logs in $LicensingInSiloDirsToShow" if [ "$LicensingInSiloDirs" ] ; then for LicensingInSiloDir in $LicensingInSiloDirs ; do CatFilesInList -R "$LicensingInSiloDir" log done else echo "No Licensing folder was found in Silo." >>"$TempBody" fi ECHOL "Licensing log: /tmp/Logs/O2Spy*" CatFilesInList -N "/tmp/Logs/O2Spy" ECHOL "Licensing logs: SymantecNISCC.log in each user's /Library/Logs directory" LogWasFound=false for EachHomeDir in $ComputerUsersHomeDirs ; do if [ -f "$EachHomeDir/Library/Logs/SymantecNISCC.log" ] ; then CatFilesInList -x "$EachHomeDir/Library/Logs/SymantecNISCC.log" LogWasFound=true fi done ! $LogWasFound && echo "No logs were found." >>"$TempBody" # --- Add to report: system.log ECHOL "`$ShowUnlimitedLinesInLogs && echo Entire || echo "Last $LinesToShowInSystemLog lines of"` $SystemLog" if [ ! -f $SystemLog ] ; then echo "$SystemLog does not exist." >>"$TempBody" elif $ShowUnlimitedLinesInLogs ; then grep -ve PrintShutDownTimes $SystemLog >>"$TempBody" else grep -ve PrintShutDownTimes $SystemLog | tail -n $LinesToShowInSystemLog >>"$TempBody" fi # --- Add to report: CrashReporter logs and other Symantec logs in /Library/Logs and {each user's home dir}/Library/Logs ECHOL "CrashReporter and other Symantec logs" FilesToShow="" for UserDir in $ComputerUsersHomeDirsAndRootDir ; do [ "$UserDir" = / ] && UserDir="" FilesToShow="$FilesToShow `find "$UserDir/Library/Logs" -type f 2>/dev/null | egrep -ie "$SymantecLogGrepPattern" | egrep -ive "$SymantecLogExclusionGrepPattern" | egrep -ie "$SymantecLogExtensionsPattern"`" done FilesToShow=`echo "$FilesToShow" | grep / | sort -f | uniq` if [ "$FilesToShow" ] ; then echo "--- Log files found ---" >>"$TempBody" echo "" >>"$TempBody" echo "$FilesToShow" >>"$TempBody" echo "" >>"$TempBody" echo "--- Log file contents`$ShowUnlimitedLinesInLogs || echo " (last $LinesToShowInLibraryLogs lines)"` ---" >>"$TempBody" echo "" >>"$TempBody" fi if $ShowUnlimitedLinesInLogs ; then CatFilesInList -l "$FilesToShow" else CatFilesInList -n $LinesToShowInLibraryLogs -l "$FilesToShow" fi # --- Add to report: KextPolicy output and files ECHOL "KextPolicy info (/var/db/SystemPolicyConfiguration/KextPolicy)" if [ -f /var/db/SystemPolicyConfiguration/KextPolicy ] ; then sqlite3 /var/db/SystemPolicyConfiguration/KextPolicy ".dump" 2>/dev/null >>"$TempBody" else echo "/var/db/SystemPolicyConfiguration/KextPolicy does not exist." >>"$TempBody" fi # --- Add to report: SEP support xml files ECHOL "Symantec Endpoint Protection support xml files (Sy*.xml)" CatFilesInList "$SEPsupportDir/Sy" .xml # --- Add to report: SEP debug logs ECHOL "Symantec Endpoint Protection debug logs" CatFilesInList "$SEPlogDir/" .log # --- Add to report: install log ECHOL "`$ShowUnlimitedLinesInLogs && echo Entire || echo "Last $LinesToShowInInstallLog lines of"` /var/log/install.log" if [ ! -f /var/log/install.log ] ; then echo "/var/log/install.log does not exist." >>"$TempBody" elif $ShowUnlimitedLinesInLogs ; then cat /var/log/install.log >>"$TempBody" else tail -n $LinesToShowInInstallLog /var/log/install.log >>"$TempBody" fi # --- Add to report: Symantec entries in /var/db/com.apple.xpc.launchd/disabled.*plist ECHOL -a "Symantec entries in /var/db/com.apple.xpc.launchd/disabled.*plist" MatchingPlistWasFound=false for Plist in `ls -d /var/db/com.apple.xpc.launchd/disabled.*plist 2>/dev/null` ; do # Grab the plist entries which contain symantec, with grep separators removed SymantecEntriesInPlist=`ShowPlistContents "$Plist" | grep -A1 -ie symantec | grep -v '^-'` # If the plist contains a Symantec entry if [ "$SymantecEntriesInPlist" ] ; then echo "" >>"$TempBody" echo "$Plist" >>"$TempBody" echo "" >>"$TempBody" echo "$SymantecEntriesInPlist" >>"$TempBody" MatchingPlistWasFound=true fi done if ! $MatchingPlistWasFound ; then echo "" >>"$TempBody" echo "There were no Symantec entries found." >>"$TempBody" fi # --- Add to report: test patchers log ECHOL "Contents of $TestPatchersLogFile" if [ -f "$TestPatchersLogFile" ] ; then echo "--- Quick summary of test patchers that ran ---" >>"$TempBody" echo "" >>"$TempBody" grep "^>>>>>.*Started running" "$TestPatchersLogFile" >>"$TempBody" 2>/dev/null echo "" >>"$TempBody" echo "--- Full output from the test patchers log ---" >>"$TempBody" echo "" >>"$TempBody" cat "$TestPatchersLogFile" >>"$TempBody" 2>/dev/null else echo "The log file does not exist." >>"$TempBody" fi # Add LiveUpdate logs and datastores AddLiveUpdateFiles AddToZipArchive "/private/var/log/kernel.log" -d "Other" AddToZipArchive "$SEPsupportDir/Serdef.dat" -d "Other" # GatherSymantecInfo.command 4.0.8: no longer add this list of files in /var/folders # --- Add to zip archive: List of items in /var/folders # find /var/folders 2>"$TempFolder/$VarFolderListFileName" 1>"$TempFolder/$VarFolderListFileName" AddToZipArchive "$TempFolder/$VarFolderListFileName" -d "Other" # --- Add to zip archive: system.log* for Log in `ls -d1 "$SystemLog"* 2>/dev/null` ; do AddToZipArchive "$Log" -d "Other" done # --- Added to zip archive: Norton Online Backup logs if [ -d "$NOBLUSupportDir" ] ; then NOBULogFiles=`ls -d "$NOBLUSupportDir/Log.txt" "$NOBLUSupportDir/nobud.log" 2>/dev/null` # Find the latest *.SLG file NOBUSLGFiles=`find "$NOBLUSupportDir/work" -iname "*.SLG" -type f 2>/dev/null | sort -f | tail -n 1` if [ "$NOBULogFiles$NOBUSLGFiles" ] ; then NOBULogsDirForReport="$TempSymantecInfoFolder/NOBU_LOGS" mkdir "$NOBULogsDirForReport" chmod 777 "$NOBULogsDirForReport" NOBUFiles="$NOBULogFiles $NOBUSLGFiles" for File in $NOBUFiles ; do ditto "$File" "$NOBULogsDirForReport" done fi fi # --- Add to zip archive: /Library/Application Support/Symantec/Silo/*/Licensing/NIS.* LicensingFiles=`ls -d "/Library/Application Support/Symantec/Silo/"*"/Licensing/NIS."* 2>/dev/null` for LicensingFileToAdd in $LicensingFiles ; do SiloFolderName=`echo "$LicensingFileToAdd" | awk -F / '{print $6}'` AddToZipArchive "$LicensingFileToAdd" -d "Licensing/$SiloFolderName" done # --- Add to zip archive: /var/db/SystemPolicyConfiguration AddToZipArchive /var/db/SystemPolicyConfiguration -d "Other" CreateFinalReport ExitScript 0 # *** End of Commands to Execute ***

Comments

Popular posts from this blog

Restore macOS Server from a Time Machine backup

JAMF Server Upgrade process

Creating a Custom Installer for Mac (PKG Package)