Run:
./SymantecRemovalTool.command| #!/bin/sh | |
| # Copyright © 2021 Broadcom. All rights reserved. | |
| # The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. This software | |
| # and all information contained therein is confidential and proprietary and shall not | |
| # be duplicated, used, disclosed or disseminated in any way except as authorized by | |
| # the applicable license agreement, without the express written permission of Broadcom. | |
| # All authorized reproductions must be marked with this language. | |
| # | |
| # EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE EXTENT PERMITTED BY | |
| # APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS APPLICABLE LICENSE AGREEMENT, BROADCOM | |
| # PROVIDES THIS DOCUMENTATION “AS IS” WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT | |
| # LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, | |
| # OR NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO THE END USER OR ANY THIRD | |
| # PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR INDIRECT, FROM THE USE OF THIS DOCUMENTATION, | |
| # INCLUDING WITHOUT LIMITATION, LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, | |
| # GOODWILL, OR LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF | |
| # THE POSSIBILITY OF SUCH LOSS OR DAMAGE. | |
| # File Name: SymantecRemovalTool.command | |
| Version=8.0.3 | |
| # | |
| # WARNING: This script will remove all files and folders created by | |
| # Symantec OS X products and any files within those folders. | |
| # Therefore, you will lose ALL files that reside in those folders, | |
| # including any that you have created. | |
| # | |
| # Usage: SymantecRemovalTool.command [options] [volume ...] | |
| # | |
| # Summary: See ShowHelp() function. | |
| # *** Variable Initializations *** | |
| PATH=/bin:/sbin:/usr/bin:/usr/sbin | |
| SymantecCleanupRestartFile="/private/tmp/com.symantec.cleanup.restart" | |
| AbbreviatedScriptName=`basename "$0" .command 2>/dev/null` | |
| AutoRunScript=true | |
| BackupLogLocationRootDirName="SymantecDiagnosticLogs" | |
| BackupLogLocationRootDir="/private/var/tmp/$BackupLogLocationRootDirName" | |
| CurrentVolumeBeingUsed="/" | |
| # DefaultsDomainsToDelete is a list of domains to delete via defaults, with the | |
| # list delimited by newlines | |
| DefaultsDomainsToDelete="group.symantec.nortonclean" | |
| ExitCodeWhenSomeFileWasNotRemoved=0 | |
| ExitCodeWhenFilesRemain=7 | |
| # FilesThatDoNotRequireRebootPattern: paths that match this pattern will not trigger a reboot | |
| FilesThatDoNotRequireRebootPattern='\.log|\.txt|\.rtf|Caches/com.apple.helpd|/log/|/Logs/|/tmp/' | |
| FilesRemovedList="/private/tmp/${AbbreviatedScriptName}RemovesThese.txt" | |
| FilesRemovedFilesOnlyList="/private/tmp/${AbbreviatedScriptName}RemovesThese-FilesOnly.txt" | |
| FilesRemovedListOfOld="/Users/Shared/${AbbreviatedScriptName}RemovesThese.txt" | |
| FilesWereSaved=false | |
| FinishedExitCode=0 | |
| FullScriptName=`basename "$0" 2>/dev/null` | |
| # ----- ItemsThatShouldRemainAfterUninstall BEGIN ------------------------------------------------ | |
| # Provide full paths of items that should remain after product uninstaller is used. | |
| # ItemsThatShouldRemainAfterUninstall is used when the -u option is passed to this | |
| # script to remove from the list of remaining files the items that exist in a folder | |
| # that this script removes entirely, such as "/Library/Application Support/Symantec". | |
| ItemsThatShouldRemainAfterUninstall="/Library/Application Support/Symantec/Daemon/Data2.chk | |
| /var/tmp/com.symantec.mes.patcher.log" | |
| # ----- ItemsThatShouldRemainAfterUninstall END -------------------------------------------------- | |
| LANG="" | |
| LaunchLocationGrepPattern='/Library/Application Support/Symantec/Uninstaller\|\.app/Contents/Resources' | |
| # ----- ListOfProgramsThatShouldNotBackUpLogs BEGIN ------------------------------------------------ | |
| ListOfProgramsThatShouldNotBackUpLogs="RemoveSymantecMacFiles.command | |
| SymantecRemovalTool | |
| SymantecRemovalTool.command" | |
| # ----- ListOfProgramsThatShouldNotBackUpLogs END -------------------------------------------------- | |
| ListOfProgramsThatShouldNotKillProcesses="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveFSDFolders="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveInstallerLaunchAgents="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveLogs="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveMDMProfile="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveMidDat="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveMigrationFiles="SymantecRemovalTool" | |
| ListOfProgramsThatShouldNotRemoveSymantecIPUA="SymantecRemovalTool" | |
| LogFile="/private/tmp/${AbbreviatedScriptName}Log.txt" | |
| LogFileOfOld="/Users/Shared/${AbbreviatedScriptName}Log.txt" | |
| # ----- LoginKeychainPasswordsToDelete BEGIN ------------------------------------------------ | |
| # (2 fields, tab delimited): | |
| # Item to delete / help text to show | |
| LoginKeychainPasswordsToDelete="com.norton.NFM.auth Norton Internet Security account info | |
| com.norton.mexico.auth Norton Zone saved sessions" | |
| # ----- LoginKeychainPasswordsToDelete END -------------------------------------------------- | |
| LogsToBackUpPattern="/Logs/" | |
| LogsToNotBackUpPattern="SymantecTestPatchers\.log" | |
| # ----- NotRemovedByNIS6Uninstaller BEGIN ------------------------------------------------ | |
| # A list of paths or partial paths that aren't removed by NIS 6 uninstaller. | |
| # Add only items that cannot be isolated by the -u option. | |
| NotRemovedByNIS6Uninstaller='/com.symantec.errorreporting. | |
| /etc/liveupdate.conf' | |
| # ----- NotRemovedByNIS6Uninstaller END -------------------------------------------------- | |
| NotRemovedByNIS6UninstallerText=" [should not be removed by NIS 6 uninstaller]" | |
| # ----- NotRemovedBySymantecUninstallerPattern BEGIN ------------------------------------------------ | |
| # A list of paths or partial paths that aren't removed by Symantec Uninstaller.app. | |
| # Add only items that cannot be isolated by the -u option. | |
| NotRemovedBySymantecUninstallerPattern='/Library/LaunchAgents/com.symantec.SCSInstaller.plist | |
| /Library/LaunchDaemons/com.symantec.nis.uninstall.plist | |
| /Library/LaunchDaemons/com.symantec.NWPService.plist | |
| /Library/Logs/SymantecTestPatchers.log | |
| /Library/Preferences/com.norton.WiFiPrivacy.plist | |
| /Library/Preferences/com.symantec.antivirus.special.plist' | |
| # ----- NotRemovedBySymantecUninstallerPattern END -------------------------------------------------- | |
| NotRemovedBySymantecUninstallerText=" [should not be removed by Symantec Uninstaller.app]" | |
| PrivateLinksPattern='^/etc/|^/tmp/|^/var/' | |
| PrivateDirectoriesPattern='^/private/etc/|^/private/tmp/|^/private/var/' | |
| PublicVersion=true | |
| # ----- ReceiptsTable BEGIN ------------------------------------------------ | |
| # (2 fields, tab delimited): | |
| # Receipt name / Receipt option (-a = delete receipt*, -s = skip run of predelete script) | |
| ReceiptsTable=' | |
| # Check to make sure there are no vague receipts that may be used by | |
| # third party software before releasing to the public. | |
| # This line may need to be removed to avoid deleting third party files: | |
| CompatibilityCheck.pkg | |
| # This line may need to be removed to avoid deleting third party files: | |
| Decomposer.pkg | |
| # This line may need to be removed to avoid deleting third party files: | |
| DeletionTracking.pkg | |
| FileSaver.pkg | |
| LiveUpdate -a | |
| NATRemoteLock.pkg | |
| NATSDPlugin.pkg | |
| NAVContextualMenu.pkg | |
| NAVcorporate.pkg | |
| NAVDefs.pkg | |
| NAVEngine.pkg | |
| NAVWidget.pkg | |
| navx.pkg | |
| NAV_App -a | |
| NAV_AutoProtect -a | |
| NFSCore.pkg | |
| NISLaunch.pkg | |
| Norton AntiVirus Application.pkg | |
| Norton AntiVirus Product Log.rtf | |
| Norton AntiVirus.pkg | |
| Norton AutoProtect.pkg | |
| Norton Disk Editor X.pkg | |
| Norton Internet Security Log.rtf | |
| Norton Personal Firewall 3.0 Log.rtf | |
| Norton Scheduled Scans.pkg | |
| Norton Scheduler.pkg | |
| Norton SystemWorks 3.0 Log.rtf | |
| Norton Utilities 8.0 Log.rtf | |
| nortonanti-theftPostflight.pkg | |
| nortonantitheftPostflight.pkg | |
| NortonAutoProtect.pkg | |
| # Remove all NortonAVDefs receipts | |
| NortonAVDefs -a | |
| NortonDefragger.pkg | |
| NortonDiskDoctor.pkg | |
| NortonFirewall -a | |
| NortonInternetSecurity -a | |
| NortonLauncher.pkg | |
| NortonParentalControl.pkg | |
| NortonPersonalFirewall.pkg | |
| NortonPersonalFirewallMenu.pkg | |
| NortonPrivacyControl.pkg | |
| NortonQuickMenu -a | |
| NPC Installer Log | |
| NPC.pkg | |
| NSMCore.pkg | |
| NSMCore.Universal.pkg | |
| NSWLaunch.pkg | |
| NUMCompatibilityCheck.pkg | |
| NumDocs.pkg | |
| NUMLaunch.pkg | |
| PredeleteTool.pkg | |
| SavLog.pkg | |
| # This line may need to be removed to avoid deleting third party files: | |
| Scheduled Scans.pkg | |
| # This line may need to be removed to avoid deleting third party files: | |
| Scheduler.pkg | |
| SDProfileEditor.pkg | |
| SMC.pkg | |
| SNAC.pkg | |
| SpeedDisk.pkg | |
| # NAV 9 installs the StuffIt engine if it needs to and creates the | |
| # StuffIt.pkg receipt for it. The following line may need to be removed | |
| # (but should not need to be) to avoid deleting third party files: | |
| StuffIt.pkg | |
| Symantec Alerts.pkg | |
| Symantec AntiVirus.pkg | |
| Symantec AutoProtect Prefs.pkg | |
| Symantec AutoProtect.pkg | |
| Symantec Decomposer.pkg | |
| Symantec Endpoint Protection.pkg | |
| Symantec Scheduled Scans.pkg | |
| Symantec Scheduler.pkg | |
| # Remove all SymantecAVDefs receipts | |
| SymantecAVDefs -a | |
| SymantecClientFirewall.pkg | |
| SymantecDecomposer.pkg | |
| SymantecDeepSightExtractor.pkg | |
| SymantecParentalControl.pkg | |
| SymantecQuickMenu.pkg | |
| SymantecSAQuickMenu.pkg | |
| SymantecSharedComponents -a | |
| SymantecUninstaller -a | |
| SymantecURLs.pkg | |
| SymAV10StuffItInstall.pkg | |
| SymAVScanServer.pkg | |
| SymConfidential -a | |
| SymConfidentialData.pkg | |
| SymDaemon -a | |
| SymDC.pkg | |
| SymDiskMountNotify.pkg | |
| SymErrorReporting.pkg | |
| SymEvent.pkg | |
| SymFileSecurity -a | |
| SymFirewall -a | |
| SymFS.pkg | |
| SymHelper.pkg | |
| SymHelpScripts.pkg | |
| SymInstallExtras.pkg | |
| SymInternetSecurity.pkg | |
| SymIntrusionPrevention -a | |
| SymIPS.pkg | |
| SymLicensing -a | |
| SymNCOApplication -a | |
| SymOxygen.pkg | |
| SymOSXKernelUtilities.pkg | |
| SymPersonalFirewallCore -a | |
| SymPersonalFirewallUI -a | |
| SymProtector.pkg | |
| SymPseudoLicensing -a | |
| SymSetupAssistant -a | |
| SymSharedFrameworks -a | |
| SymSharedSettings -a | |
| SymStuffit.pkg | |
| SymSubmission.pkg | |
| SymUIAgent -a | |
| SymWebFraud -a | |
| SymWebKitUtils.pkg | |
| Unerase.pkg | |
| # This line may need to be removed to avoid deleting third party files: | |
| URL.pkg | |
| VolumeAssist.pkg | |
| VolumeRecover.pkg | |
| WCIDEngine.pkg | |
| Wipe Info.pkg | |
| ZoneStandalone.pkg | |
| ' | |
| # ----- ReceiptsTable END -------------------------------------------------- | |
| # ----- RequiredPrograms BEGIN ------------------------------------------------ | |
| RequiredPrograms=' | |
| awk | |
| basename | |
| cat | |
| cd | |
| chmod | |
| cp | |
| crontab | |
| date | |
| defaults | |
| dirname | |
| echo | |
| egrep | |
| expr | |
| find | |
| grep | |
| head | |
| kill | |
| ls | |
| mkdir | |
| more | |
| printf | |
| ps | |
| pwd | |
| read | |
| rm | |
| sed | |
| sort | |
| sudo | |
| tail | |
| tr | |
| uniq | |
| ' | |
| # ----- RequiredPrograms END -------------------------------------------------- | |
| SavedFilesDir="/private/tmp/${AbbreviatedScriptName}SavedFiles" | |
| # *** Function Declarations *** | |
| CompareMacOSVersion() | |
| { | |
| # CompareMacOSVersion | |
| # $1 major version, $2 minor version | |
| # return | |
| # 255 current version less than input version | |
| # 0 current version equal to input version | |
| # 1 current version great than input version | |
| OSXVersion=`cat /System/Library/CoreServices/SystemVersion.plist 2>/dev/null | tr '\015' '\012' | grep . | grep -A1 '<key>ProductVersion' | tail -n 1 | grep '<string>1.\.' | awk -F '>' '{print $2}' | awk -F '<' '{print $1}'` | |
| major=`printf "%s" "$OSXVersion" | awk -F . '{print $1}'` | |
| minor=`printf "%s" "$OSXVersion" | awk -F . '{print $2}'` | |
| if [ $major -lt $1 ] ; then | |
| return 255 | |
| fi | |
| if [ $major -gt $1 ] ; then | |
| return 1 | |
| fi | |
| if [ $minor -lt $2 ] ; then | |
| return 255 | |
| fi | |
| if [ $minor -gt $2 ] ; then | |
| return 1 | |
| fi | |
| return 0 | |
| } | |
| IsSilentUninstallableSingleAgent() | |
| { | |
| # 0 uninstallable 1 cannot silently uninstall | |
| local SwithScript="/Library/Application Support/Symantec/Silo/MES/Frameworks/ProductSupport.framework/Resources/smc.sh" | |
| if [ -f "${SwithScript}" ]; then | |
| ContainsActivateSystemExtension "/Applications/Symantec Endpoint Protection.app" | |
| return $? | |
| fi | |
| return 0 | |
| } | |
| AssignVolume() | |
| { | |
| # Usage: AssignVolume $1 | |
| # Argument: $1 = Volume name. The name can begin with "/Volumes/" | |
| # unless it is "/" (boot volume). | |
| # Summary: Assigns the name of the volume passed as $1 to VolumesToUse. | |
| # If volume is assigned, 0 is returned; else, 1 is returned. | |
| # | |
| # If nothing passed, skip assignment | |
| [ -z "$1" ] && return 1 | |
| VolumeToAssign=`CheckIfValidVolume "$1"` | |
| if [ -z "$VolumeToAssign" ] ; then | |
| VolumeToAssign=`CheckIfValidVolume "/Volumes/$1"` | |
| [ -z "$VolumeToAssign" ] && return 1 | |
| fi | |
| [ "$VolumeToAssign" = "/" ] && BootVolumeWillBeSearched=true | |
| VolumesToUse="$VolumesToUse | |
| $VolumeToAssign" | |
| return 0 | |
| } | |
| BackupLog() | |
| { | |
| # Usage: BackupLog file | |
| # Summary: Copies file into BackupLogLocationDir. | |
| # BackupLogLocationDir must be defined prior | |
| # to running this function. | |
| # | |
| local FileToBackUp="$1" | |
| local BackupNumber=0 | |
| FileToBackupBase=`basename "$FileToBackUp"` | |
| local DestinationFileName | |
| if ! $DoBackupLogs ; then | |
| return | |
| elif [ ! -f "$FileToBackUp" ] ; then | |
| return | |
| # Else if this is not a file that should be backed up | |
| elif [ -z "`printf "%s" "$FileToBackUp" | egrep -ie "$LogsToBackUpPattern" | egrep -ive "$LogsToNotBackUpPattern"`" ] ; then | |
| return | |
| fi | |
| if [ ! -d "$BackupLogLocationDir" ] ; then | |
| mkdir -p "$BackupLogLocationDir" | |
| chmod 777 "$BackupLogLocationDir" "$BackupLogLocationRootDir" | |
| fi | |
| DestinationFileName="$FileToBackupBase" | |
| while [ -f "$BackupLogLocationDir/$DestinationFileName" ] ; do | |
| let BackupNumber=$BackupNumber+1 | |
| # If file name contains a period with a character on each side and no other periods | |
| if [ "`printf "%s" "$FileToBackupBase" | grep -e '.\..' | grep -ve '\..*\.'`" ] ; then | |
| DestinationFileName=`printf "%s" "$FileToBackupBase" | awk -v NUM="$BackupNumber" '{ | |
| # Put hyphen + NUM in front of the period | |
| sub("\\\.", "-" NUM ".", $0) | |
| print $0}'` | |
| else | |
| # Put hyphen + NUM at end of the file name | |
| DestinationFileName="$FileToBackupBase-$BackupNumber" | |
| fi | |
| done | |
| ditto "$FileToBackUp" "$BackupLogLocationDir/$DestinationFileName" | |
| chmod 666 "$BackupLogLocationDir/$DestinationFileName" | |
| } | |
| CheckIfValidVolume() | |
| { | |
| # Usage: CheckIfValidVolume volume | |
| # Summary: If volume is a valid volume path, the path, with extra | |
| # slashes removed, is written to standard output. | |
| # | |
| local PathToPrint="" | |
| local VolumePathToCheck="$1" | |
| # If VolumePathToCheck is the boot volume | |
| if [ "$VolumePathToCheck" -ef / ] ; then | |
| PathToPrint=/ | |
| # Else if VolumePathToCheck begins with / | |
| elif [ "`printf "%s" "$VolumePathToCheck" | grep '^/'`" ] ; then | |
| # If it is a directory and not a link | |
| if [ -d "$VolumePathToCheck" -a ! -L "$VolumePathToCheck" ] ; then | |
| # Strip any extra slashes | |
| VolumePathToCheck=`printf "%s" "$VolumePathToCheck" | sed 's|//*|/|g'` | |
| if [ "`dirname "$VolumePathToCheck"`" = "/Volumes" ] ; then | |
| PathToPrint="/Volumes/`basename "$VolumePathToCheck"`" | |
| fi | |
| fi | |
| fi | |
| [ "$PathToPrint" ] && echo "$PathToPrint" | |
| } | |
| DeleteCrontabEntries() | |
| { | |
| # Usage: DeleteCrontabEntries [$1] | |
| # Argument: $1 = Volume name. The name should begin with "/Volumes/" | |
| # unless it is "/" (boot volume). If NULL, then / is | |
| # used as volume name. | |
| # Authors: John Hansen, Corey Swertfager | |
| # Summary: Deletes from / or volume specified the crontab entries | |
| # created by Norton Scheduler and Symantec Scheduler. | |
| # Note: User must be root when calling this function. | |
| # | |
| if [ "z$1" = z/ ] ; then | |
| VolumeToDeleteCrontabsFrom="" | |
| else | |
| VolumeToDeleteCrontabsFrom="$1" | |
| fi | |
| CRONDIRNEW="$VolumeToDeleteCrontabsFrom/private/var/at/tabs" # OS 10.5 and later crontab directory | |
| CRONDIROLD="$VolumeToDeleteCrontabsFrom/private/var/cron/tabs" # OS 10.4 and earlier crontab directory | |
| if [ ! -d "$CRONDIRNEW" -a ! -d "$CRONDIROLD" ] ; then | |
| if $CreateFilesRemovedListOnly ; then | |
| if [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| echo "No crontab directory was found on on the current boot volume." >> "$FilesRemovedList" | |
| else | |
| echo "No crontab directory was found on on the volume \"`basename "$VolumeToDeleteCrontabsFrom"`\"." >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| else | |
| if [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| echo "No crontab directory was found on on the current boot volume." | |
| else | |
| echo "No crontab directory was found on on the volume \"`basename "$VolumeToDeleteCrontabsFrom"`\"." | |
| fi | |
| fi | |
| return 1 | |
| fi | |
| TEMPFILETEMPLATE="/private/tmp/NortonTemp" | |
| GREP1="^#SqzS" | |
| GREP2="^#SYMANTEC SCHEDULER CRON ENTRIES" | |
| GREP3="^#PLEASE DO NOT EDIT\.$" | |
| GREP4="EvType1=.*EvType2=.*Sched=" | |
| GREP5="Norton Solutions Support/Scheduler/schedLauncher" | |
| GREP6="Symantec/Scheduler/SymSecondaryLaunch.app/Contents/schedLauncher" | |
| SymantecCrontabEntryExists=false | |
| CurrentDir="`pwd`" # Save initial directory location | |
| # Set IFS to only newline to get all crontabs | |
| IFS=' | |
| ' | |
| for CRONDIR in `ls -d "$CRONDIRNEW" "$CRONDIROLD" 2>/dev/null` ; do | |
| cd "$CRONDIR" | |
| # List each crontab, pipe through grep command and replace | |
| for user in $ComputerUsers ; do | |
| # If there is no crontab file for this user, skip user | |
| [ ! -f "$user" ] && continue | |
| # If deleting from boot volume | |
| if [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| # Check to see if there is a Symantec crontab entry | |
| if [ "`crontab -u "$user" -l | grep -c "$GREP1\|$GREP2\|$GREP3\|$GREP4\|$GREP5\|$GREP6"`" != 0 ] ; then | |
| SymantecCrontabEntryExists=true | |
| else | |
| continue # Nothing to remove, skip user | |
| fi | |
| $CreateFilesRemovedListOnly && break | |
| TEMPFILE="$TEMPFILETEMPLATE`date +"%Y%m%d%H%M%S"`" | |
| crontab -u "$user" -l | grep -v "$GREP1\|$GREP2\|$GREP3\|$GREP4\|$GREP5\|$GREP6" > $TEMPFILE | |
| # Restore crontab file if it has more entries, else remove | |
| if [ -s "$TEMPFILE" ] ; then | |
| crontab -u "$user" $TEMPFILE &>/dev/null | |
| else | |
| echo "y" | crontab -u "$user" -r &>/dev/null | |
| fi | |
| else | |
| # Check to see if there is a Symantec crontab entry | |
| if [ "`grep -c "$GREP1\|$GREP2\|$GREP3\|$GREP4\|$GREP5\|$GREP6" "$user"`" != 0 ] ; then | |
| SymantecCrontabEntryExists=true | |
| else | |
| continue # Nothing to remove, skip user | |
| fi | |
| $CreateFilesRemovedListOnly && break | |
| TEMPFILE="$TEMPFILETEMPLATE`date +"%Y%m%d%H%M%S"`" | |
| grep -v "$GREP1\|$GREP2\|$GREP3\|$GREP4\|$GREP5\|$GREP6" "$user" > $TEMPFILE | |
| # Restore crontab file if it has more entries, else remove | |
| if [ -s "$TEMPFILE" ] ; then | |
| cat $TEMPFILE >"$user" | |
| else | |
| rm -f "$user" 2>/dev/null | |
| fi | |
| fi | |
| /bin/rm "$TEMPFILE" 2>/dev/null | |
| done | |
| [ $CreateFilesRemovedListOnly = true -a $SymantecCrontabEntryExists = true ] && break | |
| done | |
| cd "$CurrentDir" # Return to intial directory | |
| if $SymantecCrontabEntryExists ; then | |
| if $CreateFilesRemovedListOnly ; then | |
| if [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| echo "Symantec crontab entries would be deleted from the current boot volume." >> "$FilesRemovedList" | |
| else | |
| echo "Symantec crontab entries would be deleted from the volume" >> "$FilesRemovedList" | |
| echo "\"`basename "$VolumeToDeleteCrontabsFrom"`\"." >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| else | |
| if [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| echo "Symantec crontab entries were deleted from the current boot volume." | |
| else | |
| echo "Symantec crontab entries were deleted from the volume" | |
| echo "\"`basename "$VolumeToDeleteCrontabsFrom"`\"." | |
| fi | |
| fi | |
| NoFilesToRemove=false | |
| else | |
| if $CreateFilesRemovedListOnly ; then | |
| if [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| echo "There are no Symantec crontab entries on the current boot volume;" >> "$FilesRemovedList" | |
| echo "no crontab entries would be removed from it." >> "$FilesRemovedList" | |
| else | |
| echo "There are no Symantec crontab entries on the volume \"`basename "$VolumeToDeleteCrontabsFrom"`\";" >> "$FilesRemovedList" | |
| echo "no crontabs would be adjusted on that volume." >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| elif [ -z "$VolumeToDeleteCrontabsFrom" ] ; then | |
| echo "There are no Symantec crontab entries to delete from the current boot volume." | |
| else | |
| echo "There are no Symantec crontab entries to delete from the volume" | |
| echo "\"`basename "$VolumeToDeleteCrontabsFrom"`\"." | |
| fi | |
| fi | |
| return 0 | |
| } | |
| DeleteDefaults() | |
| { | |
| # Usage: DeleteDefaults | |
| # Summary: Deletes defaults for each domain in DefaultsDomainsToDelete | |
| # for each user in ComputerUsers. | |
| # GetComputerUsers() function must be run before calling this | |
| # function so that ComputerUsers is defined. | |
| # | |
| local EachDefaultsDomain | |
| local SaveIFS="$IFS" | |
| local User | |
| IFS=' | |
| ' | |
| for EachDefaultsDomain in $DefaultsDomainsToDelete ; do | |
| for User in $ComputerUsers ; do | |
| # if there are defaults set for this user and domain | |
| if [ "`sudo -u "$User" defaults read "$EachDefaultsDomain" 2>/dev/null`" ] ; then | |
| echo "Deleting defaults for $EachDefaultsDomain for user $User" | |
| sudo -u "$User" defaults delete "$EachDefaultsDomain" | |
| fi | |
| done | |
| done | |
| IFS="$SaveIFS" | |
| } | |
| DeleteLaunchdPlists() | |
| { | |
| # Usage: DeleteLaunchdPlists [$1] | |
| # Argument: $1 = Volume name. The name should begin with "/Volumes/" | |
| # unless it is "/" (boot volume). If NULL, then / is | |
| # used as volume name. | |
| # Summary: Deletes from / or volume specified the launchd plists | |
| # created by Symantec Scheduler. | |
| # Note: User must be root when calling this function. | |
| # | |
| if [ "z$1" = z/ ] ; then | |
| VolumeToDeleteLaunchdPlistsFrom="" | |
| else | |
| VolumeToDeleteLaunchdPlistsFrom="$1" | |
| fi | |
| LaunchdPlists=`ls -d "$VolumeToDeleteLaunchdPlistsFrom/Library/LaunchDaemons/com.symantec.Sched"*.plist 2>/dev/null` | |
| if [ "$LaunchdPlists" ] ; then | |
| if $CreateFilesRemovedListOnly ; then | |
| if [ -z "$VolumeToDeleteLaunchdPlistsFrom" ] ; then | |
| echo "Symantec Scheduler launchd plists would be deleted from the current boot volume." >> "$FilesRemovedList" | |
| else | |
| echo "Symantec Scheduler launchd plists would be deleted from the volume" >> "$FilesRemovedList" | |
| echo "\"`basename "$VolumeToDeleteLaunchdPlistsFrom"`\"." >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| else | |
| IFS=' | |
| ' | |
| for EachPlist in $LaunchdPlists ; do | |
| rm -f "$EachPlist" 2>/dev/null | |
| done | |
| if [ -z "$VolumeToDeleteLaunchdPlistsFrom" ] ; then | |
| echo "Symantec Scheduler launchd plists were deleted from the current boot volume." | |
| else | |
| echo "Symantec Scheduler launchd plists were deleted from the volume" | |
| echo "\"`basename "$VolumeToDeleteLaunchdPlistsFrom"`\"." | |
| fi | |
| fi | |
| NoFilesToRemove=false | |
| else | |
| if $CreateFilesRemovedListOnly ; then | |
| if [ -z "$VolumeToDeleteLaunchdPlistsFrom" ] ; then | |
| echo "There are no Symantec Scheduler launchd plists on the current boot volume," >> "$FilesRemovedList" | |
| echo "so none would be removed from it." >> "$FilesRemovedList" | |
| else | |
| echo "There are no Symantec Scheduler launchd plists on the volume" >> "$FilesRemovedList" | |
| echo "\"`basename "$VolumeToDeleteLaunchdPlistsFrom"`\", so none would be removed from it." >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| elif [ -z "$VolumeToDeleteLaunchdPlistsFrom" ] ; then | |
| echo "There are no Symantec Scheduler launchd plists to delete from the current boot" | |
| echo "volume." | |
| else | |
| echo "There are no Symantec Scheduler launchd plists to delete from the volume" | |
| echo "\"`basename "$VolumeToDeleteLaunchdPlistsFrom"`\"." | |
| fi | |
| fi | |
| return 0 | |
| } | |
| DeleteSymantecLoginItems() | |
| { | |
| # Usage: DeleteSymantecLoginItems [volume] | |
| # | |
| # Argument: volume - volume from which to remove login items; volume must | |
| # begin with "/Volumes/" unless it is "/" (boot volume); if | |
| # nothing is passed, / is assumed. | |
| # | |
| # Summary: Deletes Symantec items from all com.apple.loginitems.plist and | |
| # loginwindow.plist files on volume specified. | |
| # | |
| # If a file is purged on the boot volume, file path defined by | |
| # SymantecCleanupRestartFile is created so that reboot messaging | |
| # can be displayed by scripts that use this function. | |
| # | |
| # Returns: The number of files purged. | |
| # | |
| # Note: If this function is run while booted in OS 10.1.x, it will | |
| # not be able to adjust loginwindow.plist files on an OS 10.4 | |
| # or later volume because plutil did not ship with OS 10.1.x. | |
| # | |
| # The com.apple.loginitems.plist files are not purged if | |
| # /usr/libexec/PlistBuddy does not exist (PlistBuddy first | |
| # appeared in OS 10.5). | |
| # | |
| # GetComputerUsers() function must be run before calling this | |
| # function so that ComputerUsersHomeDirsAndRootDir is defined. | |
| # | |
| # CreateFilesRemovedListOnly and FilesRemovedList variables are | |
| # used only in Symantec Cleanup scripts. | |
| # | |
| # Version: 3.0.2 | |
| # | |
| local ArrayItem | |
| local Base | |
| local Buffer | |
| local CheckSyntax | |
| local CreateFilesRemovedListOnly="$CreateFilesRemovedListOnly" | |
| local Line | |
| local NameKeyValue | |
| local NumberOfFilesPurged=0 | |
| local OriginalPlistFile | |
| local PatternOfKeyNames="Norton WiFi Privacy\.app" | |
| local PatternOfKeyNamesToExclude="Norton Solutions|Symantec|SymSecondaryLaunch|Norton" | |
| local PlistBuddyError | |
| local PropertyKeyToUse | |
| local SavedIFS="$IFS" | |
| local StartupPathPatterns="/Applications/Norton AntiVirus.app | |
| /Applications/Norton Internet Security.app | |
| /Applications/Norton Security.app | |
| /Applications/Symantec Cloud Security.app | |
| /Applications/Symantec Unified Endpoint Protection.app | |
| /Library/Application Support/Norton Solutions | |
| /Library/Application Support/Symantec | |
| /Library/StartupItems/Norton | |
| /Norton Zone.app | |
| /Scheduler/SymSecondaryLaunch.app | |
| Norton WiFi Privacy" | |
| local SymantecLoginItemsWereFound=false | |
| local SymantecLoginItemWasFound | |
| local TargetVolume="$1" | |
| local TempFileTemplate=/private/tmp/Delete_Symantec_Login_Items | |
| local TempScrapFile=${TempFileTemplate}`date +"%Y%m%d%H%M%S"`-Scrap | |
| local TempPlistFile=${TempFileTemplate}`date +"%Y%m%d%H%M%S"`-PlistCopy | |
| [ "$1" -ef / ] && TargetVolume="" | |
| [ "z$CreateFilesRemovedListOnly" != ztrue -o ! -f "$FilesRemovedList" ] && CreateFilesRemovedListOnly=false | |
| [ -z "$SymantecCleanupRestartFile" ] && SymantecCleanupRestartFile="/private/tmp/com.symantec.cleanup.restart" | |
| which plutil &>/dev/null | |
| # If plutil program is not installed | |
| if [ $? != 0 ] ; then | |
| # If running OS 10.4 or later | |
| CompareMacOSVersion 10 3 | |
| if [ $? -eq 1 ] ; then | |
| # Show message and skip plist adjustments because plists are in binary format in OS 10.4 and later | |
| if $CreateFilesRemovedListOnly ; then | |
| echo "NOTE: plutil is not installed, so loginwindow.plist files cannot be adjusted." >> "$FilesRemovedList" | |
| else | |
| echo "NOTE: plutil is not installed, so loginwindow.plist files cannot be adjusted." | |
| fi | |
| return | |
| fi | |
| fi | |
| IFS=' | |
| ' | |
| for Line in $StartupPathPatterns ; do | |
| Base=`basename "$Line" .app` | |
| if [ -z "`echo "$Base" | egrep -xe "$PatternOfKeyNamesToExclude"`" ] ; then | |
| PatternOfKeyNames="${PatternOfKeyNames}|$Base" | |
| fi | |
| done | |
| # Remove login items from loginwindow.plist files | |
| for EachHomeDir in $ComputerUsersHomeDirsAndRootDir ; do | |
| if [ "$EachHomeDir" = / ] ; then | |
| OriginalPlistFile="$TargetVolume/Library/Preferences/loginwindow.plist" | |
| else | |
| OriginalPlistFile="$TargetVolume$EachHomeDir/Library/Preferences/loginwindow.plist" | |
| fi | |
| [ ! -f "$OriginalPlistFile" ] && continue | |
| rm -rf "$TempPlistFile" 2>/dev/null | |
| cp "$OriginalPlistFile" "$TempPlistFile" | |
| CheckSyntax=true | |
| plutil -convert xml1 "$TempPlistFile" 2>/dev/null | |
| # If plutil failed to convert the plist, don't check syntax later | |
| [ $? != 0 ] && CheckSyntax=false | |
| IsBinaryFormat=false | |
| # If original plist is different than converted plist, treat it as a binary file | |
| [ -n "`diff "$OriginalPlistFile" "$TempPlistFile" 2>/dev/null`" ] && IsBinaryFormat=true | |
| # If no Symantec login item was found, skip to next file | |
| [ `grep -c -F "$StartupPathPatterns" "$TempPlistFile"` = 0 ] && continue | |
| SymantecLoginItemsWereFound=true | |
| if $CreateFilesRemovedListOnly ; then | |
| echo "Symantec login items would be removed from:" >> "$FilesRemovedList" | |
| echo " \"$OriginalPlistFile\"" >> "$FilesRemovedList" | |
| continue | |
| fi | |
| # Purge Symantec login item(s) | |
| printf "" > "$TempScrapFile" | |
| Buffer="" | |
| DoWriteBuffer=true | |
| for Line in `cat "$TempPlistFile"` ; do | |
| # If beginning of a dictionary key | |
| if [ "`printf "%s" "$Line" | grep '<dict>$'`" ] ; then | |
| [ "$Buffer" ] && echo "$Buffer" >> "$TempScrapFile" | |
| Buffer="$Line" | |
| DoWriteBuffer=true | |
| else | |
| if [ "$Buffer" ] ; then | |
| Buffer="$Buffer | |
| $Line" | |
| else | |
| Buffer="$Line" | |
| fi | |
| # If end of a dictionary key | |
| if [ "`printf "%s" "$Line" | grep '</dict>$'`" ] ; then | |
| $DoWriteBuffer && echo "$Buffer" >> "$TempScrapFile" | |
| Buffer="" | |
| DoWriteBuffer=true | |
| # Else if Symantec path was found | |
| elif [ "`printf "%s" "$Line" | grep -F "$StartupPathPatterns"`" ] ; then | |
| DoWriteBuffer=false | |
| fi | |
| fi | |
| done | |
| [ "$Buffer" ] && echo "$Buffer" >> "$TempScrapFile" | |
| # If some login item information is missing | |
| if [ `grep -c '<dict>$' "$TempScrapFile"` != `grep -c '</dict>$' "$TempScrapFile"` ] ; then | |
| echo "ERROR: Could not remove Symantec login items from:" | |
| echo " $OriginalPlistFile" | |
| # Else if syntax is to be checked and plist contains bad syntax | |
| elif [ $CheckSyntax = true -a -n "`plutil -s "$TempScrapFile" 2>/dev/null`" ] ; then | |
| echo "ERROR: Could not remove Symantec login items (plutil conversion failed) from:" | |
| echo " $OriginalPlistFile" | |
| else | |
| echo "Removing Symantec login items from:" | |
| echo " \"$OriginalPlistFile\"" | |
| cat "$TempScrapFile" > "$OriginalPlistFile" | |
| $IsBinaryFormat && plutil -convert binary1 "$OriginalPlistFile" 2>/dev/null | |
| let NumberOfFilesPurged=$NumberOfFilesPurged+1 | |
| fi | |
| done | |
| rm -f "$TempScrapFile" 2>/dev/null | |
| # Remove login items from com.apple.loginitems.plist files if PlistBuddy is installed | |
| if [ -f /usr/libexec/PlistBuddy ] ; then | |
| for EachHomeDir in $ComputerUsersHomeDirsAndRootDir ; do | |
| if [ "$EachHomeDir" = / ] ; then | |
| OriginalPlistFile="$TargetVolume/Library/Preferences/com.apple.loginitems.plist" | |
| else | |
| OriginalPlistFile="$TargetVolume$EachHomeDir/Library/Preferences/com.apple.loginitems.plist" | |
| fi | |
| [ ! -f "$OriginalPlistFile" ] && continue | |
| rm -rf "$TempPlistFile" 2>/dev/null | |
| cp "$OriginalPlistFile" "$TempPlistFile" | |
| PropertyKeyToUse=':privilegedlist:CustomListItems' | |
| NameKeyValue=`/usr/libexec/PlistBuddy "$TempPlistFile" -c "print ${PropertyKeyToUse}:0:Name" 2>/dev/null` | |
| if [ -z "$NameKeyValue" ] ; then | |
| PropertyKeyToUse=':SessionItems:CustomListItems' | |
| NameKeyValue=`/usr/libexec/PlistBuddy "$TempPlistFile" -c "print ${PropertyKeyToUse}:0:Name" 2>/dev/null` | |
| [ -z "$NameKeyValue" ] && continue | |
| fi | |
| PlistBuddyError=0 | |
| SymantecLoginItemWasFound=false | |
| ArrayItem=0 | |
| while [ "$NameKeyValue" ] ; do | |
| # If this is a Symantec login item that should be deleted | |
| if [ "`printf "%s" "$NameKeyValue" | egrep -xe "$PatternOfKeyNames"`" ] ; then | |
| SymantecLoginItemWasFound=true | |
| $CreateFilesRemovedListOnly && break | |
| /usr/libexec/PlistBuddy "$TempPlistFile" -c "delete ${PropertyKeyToUse}:$ArrayItem" 2>/dev/null | |
| PlistBuddyError=$? | |
| [ $PlistBuddyError != 0 ] && break | |
| else | |
| let ArrayItem=$ArrayItem+1 | |
| fi | |
| NameKeyValue=`/usr/libexec/PlistBuddy "$TempPlistFile" -c "print ${PropertyKeyToUse}:$ArrayItem:Name" 2>/dev/null` | |
| done | |
| $SymantecLoginItemWasFound && SymantecLoginItemsWereFound=true | |
| if $CreateFilesRemovedListOnly ; then | |
| if $SymantecLoginItemWasFound ; then | |
| echo "Symantec login items would be removed from:" >> "$FilesRemovedList" | |
| echo " \"$OriginalPlistFile\"" >> "$FilesRemovedList" | |
| fi | |
| # Else if some login item could not be deleted | |
| elif [ $PlistBuddyError != 0 ] ; then | |
| echo "ERROR: Could not remove Symantec login items from:" | |
| echo " $OriginalPlistFile" | |
| elif $SymantecLoginItemWasFound ; then | |
| echo "Removing Symantec login items from:" | |
| echo " \"$OriginalPlistFile\"" | |
| cp "$TempPlistFile" "$OriginalPlistFile" | |
| let NumberOfFilesPurged=$NumberOfFilesPurged+1 | |
| fi | |
| done | |
| fi | |
| rm -f "$TempPlistFile" 2>/dev/null | |
| if ! $SymantecLoginItemsWereFound ; then | |
| if $CreateFilesRemovedListOnly ; then | |
| echo "No Symantec login items were found." >> "$FilesRemovedList" | |
| else | |
| echo "No Symantec login items were found." | |
| fi | |
| fi | |
| $CreateFilesRemovedListOnly && echo "" >> "$FilesRemovedList" | |
| # If some Symantec items were purged from files on boot volume, trigger restart | |
| [ $NumberOfFilesPurged -gt 0 -a -z "$TargetVolume" ] && touch "$SymantecCleanupRestartFile" | |
| IFS="$SavedIFS" | |
| return $NumberOfFilesPurged | |
| } | |
| DetermineAction() | |
| { | |
| # Usage: DetermineAction | |
| # Summary: Determines which action to take based on user input. | |
| # | |
| clear | |
| echo | |
| ShowVersion | |
| echo " | |
| WARNING: This script will remove all files and folders created by Symantec | |
| OS X products (except Symantec Adminstration Console for Macintosh | |
| files) and any files within those folders. Therefore, you will | |
| lose ALL files that reside in those folders, including any that | |
| you have created. | |
| " | |
| echo "1 - Remove all Symantec files/folders." | |
| echo | |
| echo "2 - Quit. Do not remove any files." | |
| echo | |
| printf "Enter choice (1 or 2): " | |
| read choice | |
| echo | |
| case "`echo "z$choice" | awk '{print tolower(substr($0,2))}'`" in | |
| 1) # Remove files | |
| CreateFilesRemovedListOnly=false | |
| ;; | |
| 2|q|quit) # Quit | |
| echo "Program cancelled. No files were removed." | |
| ExitScript 0 | |
| ;; | |
| *) # Show choices again | |
| DetermineAction | |
| ;; | |
| esac | |
| } | |
| DisableBrowserExtensionHostAssignment() | |
| { | |
| # Usage: DisableBrowserExtensionHostAssignment | |
| # Summary: Comments out browser extension host assignment in /etc/hosts. | |
| # | |
| local BrowserExtensionHost="macplugin.norton.com" | |
| local BrowserExtensionHostPattern=`echo "$BrowserExtensionHost" | sed 's/\./\\\./g'` | |
| local BrowserExtensionHostCommentedOutPattern | |
| local HostsContent="" | |
| local HostsFile="/etc/hosts" | |
| local Line | |
| BrowserExtensionHostPattern="[[:space:]]$BrowserExtensionHostPattern[[:space:][:cntrl:]]*$" | |
| BrowserExtensionHostCommentedOutPattern="^[[:space:]]*#.*$BrowserExtensionHostPattern" | |
| # If host assignment was found in hosts file that wasn't already commented out | |
| if [ "`grep "$HostsFile" -e "$BrowserExtensionHostPattern" 2>/dev/null | egrep -ve "$BrowserExtensionHostCommentedOutPattern"`" ] ; then | |
| echo "Commenting out $BrowserExtensionHost host assignment in $HostsFile" | |
| for Line in `cat "$HostsFile" 2>/dev/null` ; do | |
| # If line is a host assignment that has not been commented out | |
| if [ "`printf "%s" "$Line" | egrep -e "$BrowserExtensionHostPattern" | egrep -ve "$BrowserExtensionHostCommentedOutPattern"`" ] ; then | |
| # Comment it out | |
| HostsContent="$HostsContent | |
| #$Line" | |
| else | |
| # Leave it as is | |
| HostsContent="$HostsContent | |
| $Line" | |
| fi | |
| done | |
| echo "$HostsContent" | grep . > "$HostsFile" | |
| fi | |
| } | |
| 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. Also removes temp | |
| # files and kills Terminal if need be. | |
| # | |
| local PadBeginning=true | |
| local PadEnd=true | |
| while [ "$1" ] ; do | |
| case "$1" in | |
| -b) | |
| PadBeginning=false | |
| ;; | |
| -e) | |
| PadEnd=false | |
| ;; | |
| *) | |
| break | |
| ;; | |
| esac | |
| shift | |
| done | |
| rm -f "$FilesRemovedList" "$FilesRemovedFilesOnlyList" "$LogFile" 2>/dev/null 1>&2 | |
| if $QuitTerminalForcefully ; then | |
| KillTerminal | |
| fi | |
| 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 program, 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 | |
| } | |
| FinishCleanup() | |
| { | |
| # Usage: FinishCleanup | |
| # Summary: Displays then deletes the file named by LogFile, a log | |
| # of files not removed by RemoveItem function, if ErrorOccurred | |
| # is true. If NoFilesToRemove is true, a message is shown | |
| # and the function is exited. If RemoveInvisibleFilesOnly | |
| # is true, a message is shown and the function is exited; | |
| # otherwise, a message is shown. Returns value assigned to | |
| # ExitCodeWhenSomeFileWasNotRemoved if ErrorOccurred is true, | |
| # 0 otherwise. | |
| # | |
| local ContainingFolder | |
| local EachItemFound | |
| local EachItemToPurge | |
| local FilesThatRemain | |
| local SavedIFS="$IFS" | |
| if $DoShowOnlyFilesThatShouldHaveBeenUninstalled ; then | |
| # Translate [ into \[ to avoid text in between [ and ] being treated as a bracket expression | |
| PatternForOmission=`echo "$NotRemovedByNIS6UninstallerText|$NotRemovedBySymantecUninstallerText" | sed 's|\[|\\\[|g'` | |
| FilesThatRemain=`cat "$FilesRemovedList" 2>/dev/null | grep '^/' | egrep -ve "$PatternForOmission"` | |
| IFS=$'\n' # Set IFS to newlines | |
| # For each item that should remain after uninstall, with periods escaped | |
| for EachItemToPurge in `echo "$ItemsThatShouldRemainAfterUninstall" | sed 's|\.|\\\.|g'` ; do | |
| # For each item found in the list of remaining files, with or without /Volume/* prefix | |
| for EachItemFound in `echo "$FilesThatRemain" | egrep -xe "$EachItemToPurge|/Volumes/[^/]+$EachItemToPurge"` ; do | |
| # Remove it from the list | |
| FilesThatRemain=`echo "$FilesThatRemain" | grep -vxe "$EachItemFound"` | |
| ContainingFolder=`dirname "$EachItemFound"` | |
| # While containing folder is in list | |
| while [ "`echo "$FilesThatRemain" | grep -xe "$ContainingFolder"`" ] ; do | |
| # If the containing folder contains another file in the list | |
| if [ "`echo "$FilesThatRemain" | grep -e "^$ContainingFolder/."`" ] ; then | |
| # Don't remove the containing folder from list | |
| break | |
| fi | |
| # Remove the containing folder from the list | |
| FilesThatRemain=`echo "$FilesThatRemain" | grep -vxe "$ContainingFolder"` | |
| ContainingFolder=`dirname "$ContainingFolder"` | |
| done | |
| # If nothing is left in the list, stop processing | |
| [ -z "$FilesThatRemain" ] && break | |
| done | |
| done | |
| IFS="$SavedIFS" | |
| if [ "$FilesThatRemain" ] ; then | |
| echo "$FilesThatRemain" | |
| return $ExitCodeWhenFilesRemain | |
| else | |
| return 0 | |
| fi | |
| elif $CreateFilesRemovedListOnly ; then | |
| clear >&2 | |
| if $UseMore ; then | |
| ShowContents "$FilesRemovedList" | |
| else | |
| cat "$FilesRemovedList" | |
| fi | |
| echo "" >&2 | |
| echo "NOTE: No files have been removed." >&2 | |
| echo "" >&2 | |
| /bin/rm -rf "$FilesRemovedList" "$FilesRemovedFilesOnlyList" 2>/dev/null 1>&2 | |
| return 0 | |
| elif $ErrorOccurred ; then | |
| echo | |
| # Display LogFile | |
| ShowContents "$LogFile" | |
| # Remove LogFile | |
| /bin/rm -rf "$LogFile" 2>/dev/null 1>&2 | |
| echo | |
| if $RemoveInvisibleFilesOnly ; then | |
| echo "NOTE: Not all of the invisible Symantec files were removed." | |
| echo " Make sure each volume passed is unlocked and accessible." | |
| else | |
| echo "NOTE: Not all folders/files were removed." | |
| echo " Perhaps a file or folder listed above is in use or a folder" | |
| echo " listed above is not empty." | |
| if $RestartMayBeNeeded ; then | |
| echo | |
| echo "Some Symantec product files have been removed from the boot volume." | |
| else | |
| if $SomeFileWasRemoved ; then | |
| echo | |
| echo "Some folders or files have been removed." | |
| fi | |
| fi | |
| fi | |
| return $ExitCodeWhenSomeFileWasNotRemoved | |
| fi | |
| if $RemoveInvisibleFilesOnly ; then | |
| if $NoFilesToRemove ; then | |
| echo "There were no invisible Symantec files to be removed." | |
| else | |
| echo "AntiVirus QuickScan and/or Symantec FS files have been removed." | |
| fi | |
| return 0 | |
| fi | |
| if $NoFilesToRemove ; then | |
| echo "There were no files that needed to be removed. No files were removed." | |
| return 0 | |
| fi | |
| $RemoveCrontabEntriesOnly && return 0 | |
| echo | |
| if $RestartMayBeNeeded ; then | |
| printf "Symantec product files have been removed from the boot volume" | |
| if $SomeFileWasRemovedFromNonBootVolume ; then | |
| echo | |
| echo "and from other volume(s) listed above." | |
| else | |
| echo "." | |
| fi | |
| else | |
| echo "Symantec product files have been removed from the above volume(s)." | |
| fi | |
| return 0 | |
| } | |
| 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 >&2 | |
| # If prompt for password | |
| if [ "$1" = "true" ] ; then | |
| ShowVersion >&2 | |
| echo >&2 | |
| sudo -k >&2 # Make sudo require a password the next time it is run | |
| echo "You must be an admin user to run this script." >&2 | |
| 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." >&2 | |
| 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` | |
| } | |
| KillNortonZone() | |
| { | |
| $CreateFilesRemovedListOnly && return | |
| ZoneProcesses=`ps -axww | grep "Norton Zone.app/Contents/MacOS/Norton Zone" | grep -v grep | awk '{print $1}'` | |
| for EachZoneAppPID in $ZoneProcesses ; do | |
| kill -9 "$EachZoneAppPID" | |
| done | |
| [ "$ZoneProcesses" ] && killall Finder | |
| } | |
| KillSymantecProcesses() | |
| { | |
| # Usage: KillSymantecProcesses [-n] [ProcessPattern [ProductName]] | |
| # | |
| # Kills Symantec processes that match extended regular expression | |
| # ProcessPattern. If ProcessPattern is not passed, all processes | |
| # that match those in ProcessPatternDefault are used. If ProductName | |
| # is passed, that name is shown when kill attempt is made; otherwise | |
| # "Symantec" is shown. | |
| # | |
| # If -n is passed as the first argument, no kill is attempted and no | |
| # output is shown. | |
| # | |
| # Returns 1 if there remains some matching process in memory, 0 if not. | |
| # | |
| # Version: 1.0.2 | |
| # | |
| # History: 1.0.1 - 07/24/2014 - Corey Swertfager: | |
| # * Added ProcessPattern and ProductName arguments. | |
| # * Added definitions of ProcessesToSkipPattern and | |
| # ProcessPatternDefault. | |
| # * Added -n option. | |
| # 1.0.2 - 08/27/2014 - Corey Swertfager: | |
| # * Now uses egrep instead of grep for process matching. | |
| # * Now excludes process that include the name of the | |
| # script that is running this function. | |
| # * Now excludes Symantec Uninstaller.app and SymantecRemovalTool | |
| # when no ProcessPattern is passed. | |
| # * Changed -c to -n in Usage. | |
| # | |
| local aUID | |
| local DoKill=true | |
| local ExclusionPattern | |
| local NoKillOption="-n" | |
| local ProcessesToSkipPattern="/LiveUpdateAdminUtility/|/SymantecRemovalTool\.command|/RemoveSymantecMacFiles\.command|/Symantec Uninstaller.app|/SymantecRemovalTool" | |
| local ProcessPattern | |
| local ProcessPatternDefault="/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" | |
| local ProductName | |
| local SavedIFS="$IFS" | |
| local UIAGENT_USERS | |
| if [ "z$1" = "z$NoKillOption" ] ; then | |
| shift | |
| DoKill=false | |
| fi | |
| ProcessPattern="$1" | |
| ProductName="$2" | |
| ExclusionPattern=`basename "$0" 2>/dev/null | sed 's/\./\\\./g'` | |
| # If script name was successfully obtained | |
| if [ "$ExclusionPattern" ] ; then | |
| # Add / + current script name to ExclusionPattern | |
| ExclusionPattern=" egrep -|/$ExclusionPattern$|/$ExclusionPattern " | |
| else | |
| ExclusionPattern=" egrep -" | |
| fi | |
| if [ -z "$ProcessPattern" ] ; then | |
| ProcessPattern="$ProcessPatternDefault" | |
| ProcessesToSkipPattern="$ExclusionPattern|$ProcessesToSkipPattern" | |
| else | |
| ProcessesToSkipPattern="$ExclusionPattern" | |
| fi | |
| if [ -z "$ProductName" ] ; then | |
| ProductName="Symantec" | |
| fi | |
| Processes=`ps -wwax | egrep -i "$ProcessPattern" | egrep -v "$ProcessesToSkipPattern" | sort -f | uniq` | |
| if [ $DoKill = true -a -n "$Processes" ] ; then | |
| IFS=' | |
| ' | |
| # If launchctl program exists, unload SymUIAgent | |
| if which launchctl &>/dev/null ; then | |
| # Code by Haridharan Nattamaig to unload SymUIAgent | |
| UIAGENT_USERS=`ps -aef | grep SymUIAgent | grep -v grep | awk '{print $1}' | sort | uniq` | |
| for aUID in ${UIAGENT_USERS} ; do | |
| id -u ${aUID} >& /dev/null | |
| if [ $? -eq 0 ] ; then | |
| echo "Unloading SymUIAgent for UID $aUID" | |
| sudo -u \#${aUID} launchctl unload /Library/LaunchAgents/com.symantec.uiagent.application.plist >& /dev/null | |
| fi | |
| done | |
| fi | |
| echo "Ending $ProductName processes..." | |
| for TheProcess in $Processes ; do | |
| echo "$TheProcess" | |
| kill -9 `echo "z $TheProcess" | awk '{print $2}'` | |
| done | |
| IFS="$SavedIFS" | |
| Processes=`ps -wwax | egrep -i "$ProcessPattern" | egrep -v "$ProcessesToSkipPattern" | sort -f | uniq` | |
| fi | |
| if [ "$Processes" ] ; then | |
| if $DoKill ; then | |
| echo "*** $ProductName processes still in memory:" | |
| echo "$Processes" | |
| fi | |
| return 1 | |
| else | |
| if $DoKill ; then | |
| echo "*** There are no $ProductName processes in memory" | |
| fi | |
| return 0 | |
| fi | |
| } | |
| KillTerminal() | |
| { | |
| ProcessLines=`ps -axww | grep -e "/Applications/Utilities/Terminal.app" | grep -v grep | sort -f` | |
| if [ -z "$ProcessLines" ] ; then | |
| return | |
| elif [ `echo "$ProcessLines" | grep . -c` -gt 1 -a $QuitTerminalForcefullyForAll = false ] ; then | |
| echo "NOTE: Terminal was launched more than once so it could not be quit." | |
| echo " Use the -QQ option to force Terminal to be quit for all users." | |
| return | |
| else | |
| echo "WARNING: Quitting Terminal." | |
| fi | |
| IFS=' | |
| ' | |
| for ProcessLine in $ProcessLines ; do | |
| ProcessID=`printf "%s" "$ProcessLine" | awk '{print $1}'` | |
| kill -9 "$ProcessID" | |
| done | |
| } | |
| ProcessAppRemoval() | |
| { | |
| # Usage: ProcessAppRemoval | |
| # Summary: If OS 10.15 or later is running, a Symantec app for 8.5 or later | |
| # is installed in /Applications, MES silo exists, and this script | |
| # is not just generating a list of installed files: prompts user to | |
| # drag app to the trash and quits; if no options were passed, also | |
| # prompts user to press return to open the /Applications folder, | |
| # and then once return is pressed quits. | |
| # | |
| local AppDir="/Applications" | |
| local SEPAppPattern="^Symantec.*Protection.*\.app" | |
| local AppPattern="^Norton.*(360|AntiVirus|Security).*\.app|$SEPAppPattern" | |
| local App | |
| local Apps | |
| local Dummy | |
| local MESSilo="/Library/Application Support/Symantec/Silo/MES" | |
| local OSXmajorVersionMinimum=15 | |
| local ProductName | |
| local SymantecSolutionsDir="$AppDir/Symantec Solutions" | |
| CompareMacOSVersion 10 15 | |
| CompareMacOSVersionResult=$? | |
| # If OS version is less than 10.15, there is no MES silo, or only generating a list of installed files | |
| if [ $CompareMacOSVersionResult -eq 255 -o ! -d "$MESSilo" -o $CreateFilesRemovedListOnly = true ] ; then | |
| # Allow script to continue | |
| return | |
| fi | |
| Apps=`ls "$AppDir" 2>/dev/null | egrep -ie "$AppPattern" | sort -f` | |
| # If no Symantec or Norton apps were found in the /Applications folder | |
| if [ -z "$Apps" ] ; then | |
| # Check for SEP in Symantec Solutions | |
| App=`ls "$SymantecSolutionsDir" 2>/dev/null | egrep -ie "$SEPAppPattern" | sort -f | head -n 1` | |
| # If SEP is not installed there | |
| if [ -z "$App" ] ; then | |
| return | |
| fi | |
| ProductName=`basename "$App" .app` | |
| clear | |
| # We must remove the .app to trigger the system extension removal. | |
| # Directly remove the /Applications/Symantec Solutions won't work. | |
| if RemoveApp "$SymantecSolutionsDir/$App"; then | |
| return | |
| else | |
| echo | |
| echo "ATTENTION: You must use the uninstall option in your product's" | |
| echo " \"$ProductName\" menu." | |
| echo | |
| if $RunScriptAsStandAlone ; then | |
| echo "Press return to open $ProductName." | |
| read Dummy | |
| open "$SymantecSolutionsDir/$App" | |
| fi | |
| ExitScript 2 | |
| fi | |
| fi | |
| clear | |
| if RemoveApp "$AppDir/$Apps"; then | |
| return | |
| else | |
| echo | |
| echo "ATTENTION: To uninstall you must drag the following from the" | |
| echo " \"$AppDir\" folder to the trash:" | |
| echo | |
| echo "$Apps" | awk '{print " " $0}' | |
| echo | |
| if $RunScriptAsStandAlone ; then | |
| echo "Press return to open the \"$AppDir\" folder." | |
| read Dummy | |
| open "$AppDir" | |
| fi | |
| ExitScript 2 | |
| fi | |
| } | |
| ProcessDummyAppRemoval() | |
| { | |
| local Dummy | |
| local DummyApplicationName=".Symantec Endpoint Protection Legacy.app" | |
| local AppDir="/Applications" | |
| local SymantecSolutionsDir="$AppDir/Symantec Solutions" | |
| local SymantecDummyApplication="$SymantecSolutionsDir/$DummyApplicationName" | |
| CompareMacOSVersion 10 15 | |
| CompareMacOSVersionResult=$? | |
| # If OS version is less than 10.15, there is no MES silo, or only generating a list of installed files | |
| if [ $CompareMacOSVersionResult -eq 255 -o $CreateFilesRemovedListOnly = true ] ; then | |
| # Allow script to continue | |
| return | |
| fi | |
| # check dummy application | |
| clear | |
| if [[ -d "$SymantecDummyApplication" ]] ; then | |
| if RemoveApp "$SymantecDummyApplication"; then | |
| return | |
| else | |
| echo | |
| echo "ATTENTION: To uninstall you must drag the following from the" | |
| echo " \"$SymantecSolutionsDir\" folder to the trash:" | |
| echo | |
| echo "$DummyApplicationName" | awk '{print " " $0}' | |
| echo | |
| if $RunScriptAsStandAlone ; then | |
| echo "Press return to open the \"$SymantecSolutionsDir\" folder. Using command+shift+. to show hide files" | |
| read Dummy | |
| open "$SymantecSolutionsDir" | |
| fi | |
| ExitScript 2 | |
| fi | |
| fi | |
| } | |
| SystemExtensionNeedUninstall() | |
| { | |
| # Usage: SystemExtensionNeedUninstall $1 | |
| # Argument: $1 = system extension Name. | |
| # Summary: check if system extension is activated enabled or activated waiting for user | |
| # return 1: system extension needs uninstall | |
| SystemExtensionName="$1" | |
| status=$(systemextensionsctl list |grep "${SystemExtensionName}" | grep -E 'activated enabled|activated waiting for user'); | |
| if [ -z "$status" ]; then | |
| return 0 | |
| else | |
| return 1 | |
| fi | |
| } | |
| ContainsActivateSystemExtension() | |
| { | |
| # Usage: ContainsActivateSystemExtension $1 | |
| # Argument: $1 = App folder. | |
| # Summary: list all of system extension and check if any of them is activated status | |
| # return 1: has activated system extension 0: doesn't contains | |
| local app="$1" | |
| if [ -z "$app" ] | [ ! -d "$app" ]; then | |
| return 0 | |
| fi | |
| local SystemExtensionFolder="${app}/Contents/Library/SystemExtensions" | |
| if [ ! -d "$SystemExtensionFolder" ]; then | |
| return 0 | |
| fi | |
| for entry in `ls "$SystemExtensionFolder"` | |
| do | |
| echo "$entry" | |
| if [[ ${entry} = *.systemextension ]]; then | |
| echo "${entry} is systemextension" | |
| local SystemExtensionName=${entry%.systemextension} | |
| echo "SystemExtensionName: ${SystemExtensionName}" | |
| SystemExtensionNeedUninstall ${SystemExtensionName} | |
| if [ $? -eq 1 ] ; then | |
| echo "find ${SystemExtensionName} need to be uninstall in ${app}" | |
| return 1 | |
| fi | |
| fi | |
| done | |
| echo "$app no system extension needs uninstall" | |
| return 0 | |
| } | |
| RemoveApp() | |
| { | |
| # Usage: RemoveApp $1 | |
| # Argument: $1 = App to remove. | |
| # Summary: Use AppleScript to move app to Trash so that system extension | |
| # will be uninstalled after reboot. | |
| local app="$1" | |
| if [ -z "$app" ] | [ ! -d "$app" ]; then | |
| return 1 | |
| fi | |
| ContainsActivateSystemExtension "$app" | |
| if [ $? -eq 0 ] ; then | |
| echo "${app} has no activated system extension, skip mv application to trash, could silently uninstall." | |
| return 0 | |
| fi | |
| $ShowFilesAsRemoved && echo "Removing $app" | |
| osascript -e "tell application \"Finder\" to delete POSIX file \"${app}\"" | |
| if [ -d "$app" ]; then | |
| echo Failed to remove $app. | |
| return 1 | |
| else | |
| $ShowFilesAsRemoved && echo $app was successfully removed. | |
| return 0 | |
| fi | |
| } | |
| 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 --- | |
| BootVolumeWillBeSearched=false | |
| CreateFilesRemovedListOnly=false | |
| DoBackupLogs=true | |
| DoKillProcesses=true | |
| DoRemoveFSDFolders=true | |
| DoRemoveInstallerLaunchAgents=true | |
| DoRemoveIPUA=true | |
| DoRemoveLogs=true | |
| DoRemoveMDMProfile=true | |
| DoRemoveMidDat=true | |
| DoRemoveMigrationFiles=true | |
| DoRunPredeleteScripts=true | |
| DoShowOnlyFilesThatShouldHaveBeenUninstalled=false | |
| OnlyRemoveSEP=false | |
| FindOption1="" | |
| FindOption2="" | |
| ListOnlyFilesThatExist=false | |
| NoFilesToRemove=true | |
| PauseBeforeRestarting=true | |
| QuitTerminalForcefully=false | |
| QuitTerminalForcefullyForAll=false | |
| QuitWithoutRestarting=false | |
| $AutoRunScript && QuitWithoutRestarting=true | |
| RemoveCrontabEntries=true | |
| RemoveCrontabEntriesOnly=false | |
| RemoveInvisibleFiles=true | |
| RemoveInvisibleFilesOnly=false | |
| RemoveFromAllVolumes=false | |
| RemoveFromOtherVolumes=false | |
| RestartAutomatically=false | |
| RestartMayBeNeeded=false | |
| ShowFilesAsRemoved=true | |
| ShowOnlyRegularFiles=false | |
| ShowPredeleteErrors=true | |
| ShowQuitMessage=true | |
| SomeFileWasRemoved=false | |
| SomeFileWasRemovedFromNonBootVolume=false | |
| SomeFileWasRemovedFromBootVolume=false | |
| UseMore=false | |
| 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) | |
| RemoveFromAllVolumes=true | |
| BootVolumeWillBeSearched=true | |
| ;; | |
| -c) | |
| RemoveCrontabEntriesOnly=true | |
| RemoveCrontabEntries=true | |
| RemoveInvisibleFilesOnly=false | |
| RemoveInvisibleFiles=false | |
| ;; | |
| -C) | |
| RemoveCrontabEntriesOnly=false | |
| RemoveCrontabEntries=false | |
| ;; | |
| -d) | |
| DoRunPredeleteScripts=false | |
| ;; | |
| -E) | |
| ShowPredeleteErrors=false | |
| ;; | |
| -e) | |
| ShowPredeleteErrors=true | |
| ;; | |
| -F) | |
| CreateFilesRemovedListOnly=true | |
| ListOnlyFilesThatExist=true | |
| ShowOnlyRegularFiles=true | |
| FindOption1=-type | |
| FindOption2=f | |
| ;; | |
| -f) | |
| ShowFilesAsRemoved=false | |
| ;; | |
| -g) | |
| DoRemoveLogs=false | |
| ;; | |
| -H) | |
| ShowUsage 0 | |
| ;; | |
| -h) | |
| ShowHelp 0 | |
| ;; | |
| -i) | |
| RemoveInvisibleFilesOnly=true | |
| RemoveInvisibleFiles=true | |
| RemoveCrontabEntries=false | |
| RemoveCrontabEntriesOnly=false | |
| ;; | |
| -I) | |
| RemoveInvisibleFilesOnly=false | |
| RemoveInvisibleFiles=false | |
| ;; | |
| -k) | |
| DoKillProcesses=false | |
| ;; | |
| -l|-R) | |
| CreateFilesRemovedListOnly=true | |
| ListOnlyFilesThatExist=true | |
| ;; | |
| -L) | |
| CreateFilesRemovedListOnly=true | |
| ListOnlyFilesThatExist=false | |
| ;; | |
| -m) | |
| UseMore=true | |
| ;; | |
| -p) | |
| PauseBeforeRestarting=false | |
| ;; | |
| -q) | |
| QuitWithoutRestarting=true | |
| RestartAutomatically=false | |
| ;; | |
| -Q) | |
| # If -Q was previously passed, treat as -QQ | |
| if $QuitTerminalForcefully ; then | |
| # Treat as if -QQ was passed | |
| QuitTerminalForcefullyForAll=true | |
| else | |
| QuitTerminalForcefullyForAll=false | |
| fi | |
| QuitTerminalForcefully=true | |
| QuitWithoutRestarting=true | |
| RestartAutomatically=false | |
| ;; | |
| -QQ) | |
| QuitTerminalForcefully=true | |
| QuitTerminalForcefullyForAll=true | |
| QuitWithoutRestarting=true | |
| RestartAutomatically=false | |
| ;; | |
| -r|-re) | |
| RestartAutomatically=true | |
| QuitWithoutRestarting=false | |
| ;; | |
| -u) | |
| DoShowOnlyFilesThatShouldHaveBeenUninstalled=true | |
| ;; | |
| -S) | |
| OnlyRemoveSEP=true | |
| ;; | |
| -V) | |
| echo $Version | |
| ExitScript 0 | |
| ;; | |
| *) | |
| AssignVolume "$CurrentArgument" # Assign it to a Volume variable | |
| # If not a valid volume | |
| if [ $? = 1 ] ; then | |
| ShowUsage 4 "ERROR: Invalid option or volume name: \"$CurrentArgument\"." | |
| fi | |
| RemoveFromOtherVolumes=true | |
| ;; | |
| esac | |
| let CurrentArgNumber=$CurrentArgNumber+1 | |
| done | |
| if $DoShowOnlyFilesThatShouldHaveBeenUninstalled ; then | |
| CreateFilesRemovedListOnly=true | |
| ListOnlyFilesThatExist=true | |
| fi | |
| [ "`echo "$ListOfProgramsThatShouldNotBackUpLogs" | grep -x "$FullScriptName"`" ] && DoBackupLogs=false | |
| [ "`echo "$ListOfProgramsThatShouldNotKillProcesses" | grep -x "$FullScriptName"`" ] && DoKillProcesses=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveFSDFolders" | grep -x "$FullScriptName"`" ] && DoRemoveFSDFolders=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveInstallerLaunchAgents" | grep -x "$FullScriptName"`" ] && DoRemoveInstallerLaunchAgents=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveLogs" | grep -x "$FullScriptName"`" ] && DoRemoveLogs=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveMDMProfile" | grep -x "$FullScriptName"`" ] && DoRemoveMDMProfile=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveMidDat" | grep -x "$FullScriptName"`" ] && DoRemoveMidDat=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveMigrationFiles" | grep -x "$FullScriptName"`" ] && DoRemoveMigrationFiles=false | |
| [ "`echo "$ListOfProgramsThatShouldNotRemoveSymantecIPUA" | grep -x "$FullScriptName"`" ] && DoRemoveIPUA=false | |
| # --- 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 | |
| } | |
| RemoveAllSymantecFiles() | |
| { | |
| # Usage: RemoveAllSymantecFiles $1 | |
| # Argument: $1 = Volume name. The name should begin with "/Volumes/" | |
| # unless it is "/" (boot volume). | |
| # Summary: Removes all OS X Symantec products' files and folders | |
| # from volume named by $1 if RemoveInvisibleFilesOnly | |
| # equals false; otherwise, removes only the invisible Symantec | |
| # files. Removes the invisible Symantec files from other | |
| # volumes that are passed to the script. Symantec crontab | |
| # entries are removed if RemoveCrontabEntries = true. | |
| # | |
| # If not a valid volume, return 1 | |
| [ -z "`CheckIfValidVolume "$1"`" ] && return 1 | |
| CurrentVolumeBeingUsed="$1" | |
| GetComputerUsers "$CurrentVolumeBeingUsed" | |
| if $CreateFilesRemovedListOnly ; then | |
| printf "" > "$FilesRemovedFilesOnlyList" | |
| echo "" >> "$FilesRemovedList" | |
| if [ `echo "$ListOfVolumesToUse" | grep -c .` -gt 1 ] ; then | |
| if [ "$1" = / ] ; then | |
| echo "------ Volume: / (current boot volume) ------" >> "$FilesRemovedList" | |
| else | |
| echo "------ Volume: \"`basename "$1"`\" ------" >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| fi | |
| fi | |
| $RemoveCrontabEntries && DeleteCrontabEntries "$1" | |
| $RemoveCrontabEntries && DeleteLaunchdPlists "$1" | |
| $RemoveCrontabEntriesOnly && return 0 | |
| ! $RemoveInvisibleFilesOnly && DeleteSymantecLoginItems "$1" | |
| if $CreateFilesRemovedListOnly ; then | |
| if ! $RemoveInvisibleFilesOnly ; then | |
| RunPredeleteScripts "$1" | |
| echo "" >> "$FilesRemovedList" | |
| fi | |
| if $ListOnlyFilesThatExist ; then | |
| echo "The following files/folders currently exist and would be removed unless" >> "$FilesRemovedList" | |
| echo "otherwise noted:" >> "$FilesRemovedList" | |
| else | |
| echo "$FullScriptName would attempt to find and remove the following:" >> "$FilesRemovedList" | |
| fi | |
| echo "" >> "$FilesRemovedList" | |
| fi | |
| RemoveInvisibleFilesFromVolume "$1" | |
| $RemoveInvisibleFilesOnly && return 0 | |
| # If not just creating a list of removed files | |
| if ! $CreateFilesRemovedListOnly ; then | |
| RunPredeleteScripts "$1" | |
| # If removing files from the boot volume | |
| if [ "z$CurrentVolumeBeingUsed" = z/ ] ; then | |
| DeleteDefaults | |
| if $DoRemoveMDMProfile ; then | |
| echo "Removing system profile if it exists: com.symc.enroll" | |
| profiles -R -p com.symc.enroll &>/dev/null | |
| fi | |
| # 7.0.55: If Norton WiFi Privacy Service is installed | |
| if [ -e "/Library/LaunchDaemons/com.symantec.NWPService.plist" ] ; then | |
| # Unload it | |
| launchctl unload /Library/LaunchDaemons/com.symantec.NWPService.plist | |
| fi | |
| # Kill Symantec processes before attempting to remove visible files (Etrack 3442959) | |
| $DoKillProcesses && KillSymantecProcesses | |
| fi | |
| fi | |
| # If not an OS X volume, return 1 | |
| [ ! -d "$1/Library/Application Support" ] && return 1 | |
| if $CreateFilesRemovedListOnly ; then | |
| $DoShowOnlyFilesThatShouldHaveBeenUninstalled || echo "Finding visible Symantec files on: $1" >&2 | |
| elif $ShowFilesAsRemoved ; then | |
| echo "Locating visible Symantec files in: $1" | |
| else | |
| echo "Removing visible Symantec files from: $1" | |
| fi | |
| cd "$1" | |
| if [ "`pwd`" = "/" ] ; then | |
| VolumePrefix="" | |
| else | |
| VolumePrefix="`pwd`" | |
| fi | |
| KillNortonZone | |
| RemoveItem "/.com_symantec_symfs_private" | |
| RemoveItem "/.symSchedScanLockxz" | |
| RemoveItem "/Applications/ApplicationNorton.app" | |
| RemoveItem "/Applications/Firefox.app/Contents/MacOS/extensions/{0e10f3d7-07f6-4f12-97b9-9b27e07139a5}" -u | |
| RemoveItem "/Applications/Firefox.app/Contents/MacOS/extensions/{29dd9c80-9ea1-4aaf-9305-a0314aba24e3}" -u | |
| RemoveItem "/Applications/Firefox.app/Contents/MacOS/extensions/[email protected]" -u | |
| RemoveItem "/Applications/GatherSymantecInfo" | |
| RemoveItem "/Applications/Late Breaking News" | |
| RemoveItem "/Applications/LiveUpdate" | |
| RemoveItem "/Applications/LiveUpdate Folder" | |
| RemoveItem "/Applications/LiveUpdate Folder (OS X)" | |
| # Remove navx incorrectly installed by NAV 800.007 installer: | |
| RemoveItem "/Applications/navx" | |
| # 7.0.55: Exclude NWP so that it doesn't show up when -u script option is used | |
| RemoveItem "/Applications/Norton " "*" -x "Norton WiFi Privacy.app" | |
| # 7.0.55: Remove NWP app | |
| RemoveItem "/Applications/Norton WiFi Privacy.app" -u | |
| RemoveItem "/Applications/Symantec AntiVirus" | |
| RemoveItem "/Applications/Symantec Cloud Security.app" | |
| RemoveItem "/Applications/Symantec Endpoint Protection.app" | |
| RemoveItem "/Applications/Symantec Endpoint Protection Cloud.app" | |
| RemoveItem "/Applications/Symantec Solutions" | |
| RemoveItem "/Applications/Symantec Unified Endpoint Protection.app" | |
| # The next 3 items are erroneously created by early builds of NAV 10 installer | |
| RemoveItem "/Applications/Symantec/LiveUpdate.app" | |
| RemoveItem "/Applications/Symantec/Read Me Files" | |
| RemoveItem "/Applications/Symantec" -e | |
| RemoveItem "/Applications/Trash Running Daemons" | |
| RemoveItem "/Applications/uDelete Preferences" | |
| RemoveItem "/Applications/Register Your Software" | |
| RemoveItem "/etc/liveupdate.conf" | |
| RemoveItem "/etc/mach_init.d/SymSharedSettings.plist" | |
| RemoveItem "/etc/Symantec.conf" | |
| # Folder erroneously created by NPF 300.001 - removed if empty: | |
| RemoveItem "/Firewall" -e -u | |
| RemoveItem "/Library/Application Support/com.symantec.NWPService" -u | |
| RemoveItem "/Library/Application Support/NAVDiagnostic.log" | |
| RemoveItem "/Library/Application Support/NAV.history" | |
| RemoveItem "/Library/Application Support/nat_" "*" -u | |
| RemoveItem "/Library/Application Support/nat_" "*" -u | |
| RemoveItem "/Library/Application Support/nav_" "*" -u | |
| RemoveItem "/Library/Application Support/nis_" "*" -u | |
| RemoveItem "/Library/Application Support/nsm_" "*" -u | |
| RemoveItem "/Library/Application Support/Norton Application Aliases" | |
| RemoveItem "/Library/Application Support/Norton Solutions Support" | |
| RemoveItem "/Library/Application Support/norton_" "*" -u | |
| RemoveItem "/Library/Application Support/o2spy.log" | |
| RemoveItem "/Library/Application Support/regid.1992-12.com.symantec" "*" | |
| RemoveItem "/Library/Application Support/Symantec" | |
| $DoRemoveIPUA && RemoveItem "/Library/Application Support/Symantec_IPUA" | |
| RemoveItem "/Library/Application Support/symantec_uninstalldashboard" "*" | |
| RemoveItem "/Library/Application Support/SymRun" | |
| RemoveItem "/Library/Authenticators/SymAuthenticator.bundle" | |
| RemoveItem "/Library/CFMSupport/Norton Shared Lib" | |
| RemoveItem "/Library/CFMSupport/Norton Shared Lib Carbon" | |
| RemoveItem "/Library/Contextual Menu Items/NAVCMPlugIn.plugin" | |
| RemoveItem "/Library/Contextual Menu Items/SAVCMPlugIn.plugin" | |
| RemoveItem "/Library/Contextual Menu Items/SymFileSecurityCM.plugin" | |
| RemoveItem "/Library/Documentation/Help/LiveUpdate Help" | |
| RemoveItem "/Library/Documentation/Help/LiveUpdate-Hilfe" | |
| RemoveItem "/Library/Documentation/Help/Norton AntiVirus Help" | |
| RemoveItem "/Library/Documentation/Help/Norton AntiVirus-Hilfe" | |
| RemoveItem "/Library/Documentation/Help/Norton Help" | |
| RemoveItem "/Library/Documentation/Help/Norton Help Scripts" | |
| RemoveItem "/Library/Documentation/Help/Norton Help Scripts Folder" | |
| RemoveItem "/Library/Documentation/Help/Norton Utilities Help" | |
| RemoveItem "/Library/Extensions/FileSecurity.kext" | |
| RemoveItem "/Library/Extensions/ndcengine.kext" | |
| RemoveItem "/Library/Extensions/NortonForMac.kext" | |
| RemoveItem "/Library/Extensions/SymAPComm.kext" | |
| RemoveItem "/Library/Extensions/SymFirewall.kext" | |
| RemoveItem "/Library/Extensions/SymInternetSecurity.kext" | |
| RemoveItem "/Library/Extensions/SymIPS.kext" | |
| RemoveItem "/Library/Extensions/SymPersonalFirewall.kext" | |
| RemoveItem "/Library/Extensions/SymXIPS.kext" | |
| RemoveItem "/Library/Frameworks/mach_inject_bundle.framework" | |
| RemoveItem "/Library/InputManagers/Norton Confidential for Safari" | |
| RemoveItem "/Library/InputManagers/Norton Safety Minder" | |
| RemoveItem "/Library/InputManagers/SymWebKitUtils" | |
| RemoveItem "/Library/Internet Plug-Ins/Norton Confidential for Safari.plugin" | |
| RemoveItem "/Library/Internet Plug-Ins/Norton Family Safety.plugin" | |
| RemoveItem "/Library/Internet Plug-Ins/Norton Safety Minder.plugin" | |
| RemoveItem "/Library/Internet Plug-Ins/NortonFamilyBF.plugin" | |
| RemoveItem "/Library/Internet Plug-Ins/NortonInternetSecurityBF.plugin" | |
| RemoveItem "/Library/Internet Plug-Ins/NortonSafetyMinderBF.plugin" | |
| RemoveItem "/Library/LaunchDaemons/com.norton" "*" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec" "*" -x 'com\.symantec\.saturn\.plist' | |
| RemoveCrashReporterLogs | |
| RemoveItem "/Library/Plug-ins/DiskImages/NUMPlugin.bundle" | |
| RemoveItem "/Library/Plug-ins/DiskImages/VRPlugin.bundle" | |
| RemoveItem "/Library/Plug-ins/DiskImages" -e -u | |
| RemoveItem "/Library/Plug-ins" -e -u | |
| RemoveItem "/Library/PreferencePanes/APPrefPane.prefPane" | |
| RemoveItem "/Library/PreferencePanes/FileSaver.prefPane" | |
| RemoveItem "/Library/PreferencePanes/Norton Family Safety.prefPane" | |
| RemoveItem "/Library/PreferencePanes/Norton Safety Minder.prefPane" | |
| RemoveItem "/Library/PreferencePanes/Ribbon.Norton.prefPane" | |
| RemoveItem "/Library/PreferencePanes/SymantecQuickMenu.prefPane" | |
| RemoveItem "/Library/PreferencePanes/SymAutoProtect.prefPane" | |
| RemoveItem "/Library/PrivateFrameworks/NPF.framework" | |
| RemoveItem "/Library/PrivateFrameworks/NPFCoreServices.framework" | |
| RemoveItem "/Library/PrivateFrameworks/NPFDataSource.framework" | |
| RemoveItem "/Library/PrivateFrameworks/PlausibleDatabase.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymAppKitAdditions.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymAVScan.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymBase.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymConfidential.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymDaemon.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymFirewall.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymInternetSecurity.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymIPS.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymIR.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymLicensing.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymNetworking.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymOxygen.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymPersonalFirewall.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymScheduler.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymSEP.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymSharedSettings.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymSubmission.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymSystem.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymUIAgent.framework" | |
| RemoveItem "/Library/PrivateFrameworks/SymUIAgentUI.framework" | |
| if [ ! -e "$VolumePrefix/Library/PrivateFrameworks/SymWebKitUtils.framework/Versions/A/Resources/SymWKULoader.dylib" \ | |
| -o \( $CreateFilesRemovedListOnly = true -a $ListOnlyFilesThatExist = false \) ] ; then | |
| RemoveItem "/Library/PrivateFrameworks/SymWebKitUtils.framework" | |
| fi | |
| RemoveItem "/Library/PrivilegedHelperTools/com.symantec" "*" -x "com\.symantec\.NWPService" | |
| RemoveItem "/Library/PrivilegedHelperTools/com.symantec.NWPService" -u | |
| RemoveItem "/Library/PrivilegedHelperTools/NATRemoteLock.app" | |
| IFS=' | |
| ' | |
| for EachReceiptLine in `echo "$ReceiptsTable" | grep . | grep -v '^#'` ; do | |
| ReceiptName=`echo "$EachReceiptLine" | awk -F " " '{print $1}'` | |
| ReceiptArg=`echo "$EachReceiptLine" | awk -F " " '{print $2}'` | |
| if [ "z$ReceiptArg" = z-a ] ; then | |
| RemoveItem "/Library/Receipts/$ReceiptName" "*" | |
| RemoveItem "/Library/Receipts/$ReceiptName"Dev "*" | |
| else | |
| if [ "z$ReceiptName" = zSymWebKitUtils.pkg -o "z$ReceiptName" = zSymWebKitUtilsDev.pkg ] ; then | |
| # If SymWKULoader exists and CleanUpSymWebKitUtils does not, skip deletion of SymWebKitUtils receipt | |
| [ -e "$VolumePrefix/Library/PrivateFrameworks/SymWebKitUtils.framework/Versions/A/Resources/SymWKULoader.dylib" -a ! -e /Library/StartupItems/CleanUpSymWebKitUtils ] && continue | |
| fi | |
| RemoveItem "/Library/Receipts/$ReceiptName" | |
| if [ "`echo "$ReceiptName" | grep '\.pkg$'`" ] ; then | |
| ReceiptName="`basename "$ReceiptName" .pkg`Dev.pkg" | |
| RemoveItem "/Library/Receipts/$ReceiptName" | |
| fi | |
| fi | |
| done | |
| RemoveItem "/Library/ScriptingAdditions/SymWebKitUtils.osax" | |
| RemoveItem "/Library/ScriptingAdditions/SymWebKitUtilsSL.osax" | |
| RemoveItem "/Library/Services/Norton for Mac.service" | |
| RemoveItem "/Library/Services/NortonDocktile.bundle" | |
| RemoveItem "/Library/Services/ScanService.service" | |
| RemoveItem "/Library/Services/Symantec" "*" | |
| RemoveItem "/Library/Services/SymSafeWeb.service" | |
| # Fix ESMAC-855 | |
| # Remove empty Services folder will impact MacOS to remove our service in "System Preferences->Keyboard->Shortcut(Services)" | |
| # That will caused user still can see "Scan with Symantec" menu when right click any folder. | |
| # RemoveItem "/Library/Services" -e -u | |
| RemoveItem "/Library/StartupItems/NortonAutoProtect" | |
| RemoveItem "/Library/StartupItems/NortonAutoProtect.kextcache" | |
| RemoveItem "/Library/StartupItems/NortonLastStart" | |
| RemoveItem "/Library/StartupItems/NortonMissedTasks" | |
| RemoveItem "/Library/StartupItems/NortonPersonalFirewall" | |
| RemoveItem "/Library/StartupItems/NortonPrivacyControl" | |
| RemoveItem "/Library/StartupItems/NUMCompatibilityCheck" | |
| RemoveItem "/Library/StartupItems/SMC" | |
| RemoveItem "/Library/StartupItems/SymAutoProtect" | |
| RemoveItem "/Library/StartupItems/SymAutoProtect.kextcache" | |
| RemoveItem "/Library/StartupItems/SymDCInit" | |
| RemoveItem "/Library/StartupItems/SymMissedTasks" | |
| RemoveItem "/Library/StartupItems/SymProtector" | |
| RemoveItem "/Library/StartupItems/SymQuickMenuOSFix" | |
| RemoveItem "/Library/StartupItems/SymWebKitUtilsOSFix" | |
| RemoveItem "/Library/StartupItems/TrackDelete" | |
| RemoveItem "/Library/StartupItems/VolumeAssist" | |
| RemoveItem "/Library/Symantec/tmp" | |
| RemoveItem "/Library/Symantec" -E -u | |
| RemoveItem "/Library/Widgets/NAV.wdgt" | |
| RemoveItem "/Library/Widgets/Symantec Alerts.wdgt" | |
| RemoveItem "/Library/Widgets" -E -u | |
| RemoveItem "/Norton AntiVirus Installer Log" | |
| # Folder with files erroneously created by an early Corsair installer: | |
| RemoveItem "/opt/Symantec" | |
| # Folder erroneously created by that Corsair installer - removed if empty: | |
| RemoveItem "/opt" -E -u | |
| # Folder erroneously created by NPF 300.001 - removed if empty: | |
| RemoveItem "/Personal" -e -u | |
| # Folder erroneously created by NPF 300.001 - removed if empty: | |
| RemoveItem "/Solutions" -e -u | |
| # Folder erroneously created by NPF 300.001 - removed if empty: | |
| RemoveItem "/Support/Norton" -e -u | |
| # Folder erroneously created by NPF 300.001 - removed if empty: | |
| RemoveItem "/Support" -e -u | |
| RemoveItem "/symaperr.log" | |
| RemoveItem "/symapout.log" | |
| # Four frameworks erroneously installed by early builds of NAV 9.0.1: | |
| RemoveItem "/SymAppKitAdditions.framework" | |
| RemoveItem "/SymBase.framework" | |
| RemoveItem "/SymNetworking.framework" | |
| RemoveItem "/SymSystem.framework" | |
| RemoveItem "/System/Library/Authenticators/SymAuthenticator.bundle" | |
| RemoveItem "/System/Library/CFMSupport/Norton Shared Lib Carbon" | |
| RemoveItem "/System/Library/CoreServices/NSWemergency" | |
| RemoveItem "/System/Library/CoreServices/NUMemergency" | |
| RemoveItem "/System/Library/Extensions/DeleteTrap.kext" | |
| RemoveItem "/System/Library/Extensions/KTUM.kext" | |
| RemoveItem "/System/Library/Extensions/ndcengine.kext" | |
| RemoveItem "/System/Library/Extensions/NortonForMac.kext" | |
| RemoveItem "/System/Library/Extensions/NPFKPI.kext" | |
| RemoveItem "/System/Library/Extensions/SymDC.kext" | |
| RemoveItem "/System/Library/Extensions/SymEvent.kext" | |
| RemoveItem "/System/Library/Extensions/symfs.kext" | |
| RemoveItem "/System/Library/Extensions/SymInternetSecurity.kext" | |
| RemoveItem "/System/Library/Extensions/SymIPS.kext" | |
| RemoveItem "/System/Library/Extensions/SymOSXKernelUtilities.kext" | |
| RemoveItem "/System/Library/Extensions/SymPersonalFirewall.kext" | |
| RemoveItem "/System/Library/Extensions/SymXIPS.kext" | |
| RemoveItem "/System/Library/StartupItems/NortonAutoProtect" | |
| RemoveItem "/System/Library/StartupItems/SymMissedTasks" | |
| RemoveItem "/System/Library/Symantec" | |
| RemoveItem "/System/Library/SymInternetSecurity.kext" | |
| RemoveItem "/SystemWorks Installer Log" | |
| RemoveItem "/tmp/com.symantec.liveupdate.reboot" | |
| RemoveItem "/tmp/com.symantec.liveupdate.restart" | |
| RemoveItem "/tmp/com.symantec.MES.liveupdate.reboot" | |
| RemoveItem "/tmp/com.symantec.NFM.liveupdate.reboot" | |
| RemoveItem "/tmp/jlulogtemp" | |
| RemoveItem "/tmp/LiveUpdate." "*" | |
| RemoveItem "/tmp/liveupdate" | |
| RemoveItem "/tmp/lulogtemp" | |
| RemoveItem "/tmp/O2Spy.log" | |
| RemoveItem "/tmp/SymSharedFrameworks" "*" | |
| RemoveItem "/tmp/symask" | |
| RemoveItem "/Users/dev/bin/smellydecode" | |
| RemoveItem "/Users/dev/bin" -E -u | |
| RemoveItem "/Users/dev" -E -u | |
| RemoveItem "/Users/Shared/NAV Corporate" | |
| RemoveItem "/Users/Shared/NIS Corporate" | |
| RemoveItem "/Users/Shared/SymantecRemovalToolRemovesThese.txt" | |
| RemoveItem "/Users/Shared/SymantecRemovalToolLog.txt" | |
| RemoveItem "/Users/Shared/RemoveSymantecMacFilesRemovesThese.txt" | |
| RemoveItem "/Users/Shared/RemoveSymantecMacFilesLog.txt" | |
| RemoveItem "/Users/Shared/SymantecRemovalToolRemovesThese.txt" | |
| RemoveItem "/Users/Shared/SymantecRemovalToolLog.txt" | |
| RemoveItem "/usr/bin/nortonscanner" | |
| RemoveItem "/usr/bin/nortonsettings" | |
| RemoveItem "/usr/bin/MigrateQTF" | |
| RemoveItem "/usr/bin/navx" | |
| RemoveItem "/usr/bin/npfx" | |
| RemoveItem "/usr/bin/savx" | |
| RemoveItem "/usr/bin/scfx" | |
| RemoveItem "/usr/bin/symsched" | |
| RemoveItem "/usr/lib/libsymsea." "dylib" | |
| RemoveItem "/usr/lib/libwpsapi.dylib" | |
| RemoveItem "/usr/local/bin/CoreLocationProviderTest" | |
| RemoveItem "/usr/local/bin/KeyGenerator" | |
| RemoveItem "/usr/local/bin/LocationProviderInterfaceTest" | |
| RemoveItem "/usr/local/bin/LocationProviderTest" | |
| RemoveItem "/usr/local/bin/MigrateQTF" | |
| RemoveItem "/usr/local/bin/navx" | |
| RemoveItem "/usr/local/bin/nortonscanner" | |
| RemoveItem "/usr/local/bin/nortonsettings" | |
| RemoveItem "/usr/local/bin/npfx" | |
| RemoveItem "/usr/local/bin/SkyhookProviderTest" | |
| RemoveItem "/usr/local/bin" -E -u | |
| RemoveItem "/usr/local/lib/libAPFeature.a" | |
| RemoveItem "/usr/local/lib/libcx_lib.so" | |
| RemoveItem "/usr/local/lib/libecomlodr.dylib" | |
| RemoveItem "/usr/local/lib/libgecko3parsers.dylib" | |
| RemoveItem "/usr/local/lib/liblux.so." "*" | |
| RemoveItem "/usr/local/lib/libnlucallback.dylib" | |
| RemoveItem "/usr/local/lib/libNUCoverFlow" "*" | |
| RemoveItem "/usr/local/lib/libsymsea." "dylib" | |
| RemoveItem "/usr/local/lib" -E -u | |
| RemoveItem "/usr/share/man/man1/NAVScanIDs.h" | |
| RemoveItem "/var/db/NATSqlDatabase.db" | |
| RemoveItem '/var/db/receipts/$(SYM_SKU_REVDOMAIN).install.bom' | |
| RemoveItem '/var/db/receipts/$(SYM_SKU_REVDOMAIN).install.plist' | |
| RemoveItem "/var/db/receipts/com.symantec" "*" -x "com\.symantec-it\..*" | |
| RemoveItem "/var/db/receipts/com.Symantec" "*" -x "com\.Symantec-it\..*" | |
| RemoveItem "/var/log/du.log" "*" | |
| RemoveItem "/var/log/dulux.log" "*" | |
| RemoveItem "/var/log/lut.log" "*" | |
| RemoveItem "/var/log/lux.log" "*" | |
| RemoveItem "/var/log/luxtool.log" "*" | |
| RemoveItem "/var/log/mexd.log" "*" | |
| RemoveItem "/var/log/microdef.log" "*" | |
| RemoveItem "/var/log/nortondns.log" | |
| RemoveItem "/var/log/Npfkernel.log.fifo" | |
| RemoveItem "/var/root/Applications/Norton Internet Security.app" | |
| RemoveItem "/var/root/Applications" -E | |
| RemoveItem "/var/root/Library/Bundles/NAVIR.bundle" | |
| RemoveItem "/var/root/Library/Bundles" -E -u | |
| RemoveItem "/var/root/Library/Contextual Menu Items/NAVCMPlugIn.plugin" | |
| RemoveItem "/var/root/Library/Contextual Menu Items" -E -u | |
| RemoveItem "/var/tmp/com.symantec" "*" | |
| RemoveItem "/var/tmp/com.Symantec" "*" | |
| $DoRemoveMigrationFiles && RemoveItem "/var/tmp/NFM" | |
| RemoveItem "/var/tmp/Data2.chk" -u | |
| RemoveItem "/var/tmp/nis_" "_Data2.chk" -u | |
| RemoveItem "/var/tmp/symantec_error_report" "*" | |
| # Delete logs listed in logging conf files within /etc/symantec | |
| IFS=' | |
| ' | |
| for LUXLogFile in `cat "/Library/Application Support/Symantec/Silo/"*"/LiveUpdate/Conf/lux.logging.conf" /etc/symantec/dulux.logging.conf /etc/symantec/lux.logging.conf /etc/symantec/microdef.logging.conf 2>/dev/null | tr '\015' '\012' | grep logger.sink.file.filePath= | awk -F = '{print $2}' | sort -f | uniq` ; do | |
| RemoveItem "$LUXLogFile" "*" | |
| done | |
| if [ -f /etc/symantec/defutils.conf ] ; then | |
| DefUtilsLogContents=`cat /etc/symantec/defutils.conf 2>/dev/null | tr '\015' '\012'` | |
| DefUtilsLogDir=`printf "%s" "$DefUtilsLogContents" | grep defutillog_dir= | awk -F = '{print $2}'` | |
| if [ "$DefUtilsLogDir" ] ; then | |
| DefUtilsLogBaseName=`printf "%s" "$DefUtilsLogContents" | grep defutillog_name= | awk -F = '{print $2}'` | |
| [ "$DefUtilsLogBaseName" ] && RemoveItem "$DefUtilsLogDir/$DefUtilsLogBaseName".log "*" | |
| fi | |
| fi | |
| if $DoRemoveMidDat ; then | |
| RemoveItem "/etc/symantec/mid.dat" -u | |
| fi | |
| RemoveItem "/etc/symantec" -d -x "saturn|mid\.dat" | |
| RemoveItem "/etc/symantec" -E -u | |
| if [ -f "$VolumePrefix/etc/syslog.conf" -a $CreateFilesRemovedListOnly = false ] ; then | |
| # Remove Norton Personal Firewall entries from /etc/syslog.conf | |
| sed -e "/Norton Personal Firewall/d" -e "/Npfkernel.log.fifo/d" "$VolumePrefix/etc/syslog.conf" > /tmp/NPF.syslog.conf | |
| if [ -s /tmp/NPF.syslog.conf ] ; then | |
| /bin/cp -f /tmp/NPF.syslog.conf "$VolumePrefix/etc/syslog.conf" | |
| fi | |
| /bin/rm -f /tmp/NPF.syslog.conf | |
| fi | |
| RemoveFilesFromLibraryAndUserDirectories "$1" | |
| RemoveItem /Library/Preferences/Network -E -u | |
| if [ -s "$FilesRemovedFilesOnlyList" ] ; then | |
| sort -f "$FilesRemovedFilesOnlyList" | uniq | grep . >> "$FilesRemovedList" | |
| fi | |
| RemoveLoginKeychainPasswords "$CurrentVolumeBeingUsed" | |
| # If removing files from the boot volume | |
| if [ $CreateFilesRemovedListOnly = false -a "z$CurrentVolumeBeingUsed" = z/ ] ; then | |
| # Kill Symantec processes and attempt to remove Symantec folder again in case Symantec | |
| # folder was re-created with incorrect permissions (Etrack 3442959) while other files | |
| # were removed | |
| $DoKillProcesses && KillSymantecProcesses &>/dev/null | |
| RemoveItem "/Library/Application Support/Symantec" | |
| fi | |
| # remove kernel extension | |
| kextcache -invalidate / | |
| } | |
| RemoveCrashReporterLogs() | |
| { | |
| # Usage: RemoveCrashReporterLogs | |
| # Summary: Removes CrashReporter logs. GetComputerUsers function must be run | |
| # and VolumePrefix must be defined before running this function. | |
| # | |
| # CrashLogGrepPattern will match visible or invisible (name begins with a period) Symantec files | |
| local CrashLogGrepPattern='/\.?com\.norton|/\.?com\.symantec|/\.?LiveUpdate|\.?/LUTool|/\.?NFM|/\.?Norton|/\.?Sym' | |
| local LogsToDelete="" | |
| local LogToDelete | |
| local UserDir | |
| IFS=' | |
| ' | |
| for UserDir in $ComputerUsersHomeDirsAndRootDir ; do | |
| [ "$UserDir" = / ] && UserDir="" | |
| LogsToDelete="$LogsToDelete | |
| `find "$VolumePrefix$UserDir/Library/Application Support/CrashReporter" "$VolumePrefix$UserDir/Library/Application Support/DiagnosticReports" "$VolumePrefix$UserDir/Library/Logs/CrashReporter" "$VolumePrefix$UserDir/Library/Logs/DiagnosticReports" "$VolumePrefix$UserDir/Library/Logs/Crashes" -type f 2>/dev/null | egrep -i "$CrashLogGrepPattern"`" | |
| done | |
| LogsToDelete=`echo "$LogsToDelete" | grep / | sort -f` | |
| if [ "$VolumePrefix" ] ; then | |
| # Remove VolumePrefix from beginning of paths | |
| LogsToDelete=`echo "$LogsToDelete" | awk -v VOLUME="$VolumePrefix" '{print substr($0,length(VOLUME)+1)}'` | |
| fi | |
| if [ "$LogsToDelete" ] ; then | |
| for LogToDelete in $LogsToDelete ; do | |
| RemoveItem "$LogToDelete" -u | |
| done | |
| fi | |
| } | |
| RemoveEmptyDirectory() | |
| { | |
| # Usage: RemoveEmptyDirectory $1 | |
| # Argument: $1 = Full path name of directory | |
| # Summary: Removes directory $1 if it is empty or if it contains | |
| # only .DS_Store and/or .localized (the next best thing | |
| # to being empty). | |
| # | |
| # If $1 is a directory and not a link | |
| if [ -d "$1" -a ! -L "$1" ] ; then | |
| # If folder contains only .DS_Store and/or .localized, or is empty | |
| if [ -z "`ls "$1" 2>/dev/null | grep -v "^\.DS_Store\|^\.localized"`" ] ; then | |
| $ShowFilesAsRemoved && echo " Removing: \"$1\"" | |
| # Clear immutable bit to remove any Finder lock | |
| chflags -R nouchg "$1" 2>/dev/null 1>&2 | |
| /bin/rm -rf "$1" 2>/dev/null 1>&2 # Remove folder | |
| fi | |
| fi | |
| } | |
| RemoveFilesFromLibraryAndUserDirectories() | |
| { | |
| # Usage: RemoveFilesFromLibraryAndUserDirectories $1 | |
| # Argument: $1 = Name of volume from which to remove preferences. | |
| # The name must begin with "/Volumes/" | |
| # unless it is "/" (boot volume). | |
| # Summary: Removes all Symantec files & folders from each user's | |
| # preferences, /Library/Caches, and /Library/Preferences. | |
| # Removes help files from /Library/Documentation. Removes | |
| # folders incorrectly created by NAV 7.0.2 from each | |
| # user's home directory. | |
| # | |
| local FSDDir | |
| local FSDDirs | |
| local InstallerAppsToRemove | |
| local InstallerAppToRemove | |
| local UserDownloadsDir | |
| local UserHomeDir | |
| local UserLibraryDir | |
| CurrentVolumeBeingUsed="$1" | |
| if [ "$1" = "/" ] ; then | |
| VolumeToCheck="" | |
| else | |
| VolumeToCheck="$1" | |
| fi | |
| # set IFS to only newline to get all user names | |
| IFS=' | |
| ' | |
| for UserHomeDir in $ComputerUsersHomeDirsAndRootDir ; do | |
| if [ "$UserHomeDir" = "/" ] ; then | |
| UserHomeDir="" | |
| fi | |
| UserLibraryDir="$UserHomeDir/Library" | |
| # If UserLibraryDir is not a directory, skip to the next name | |
| [ ! -d "$VolumeToCheck$UserLibraryDir" ] && continue | |
| cd "$VolumeToCheck/" | |
| # If a user's home directory, delete folders from user's home directory | |
| # that were incorrectly created by NAV 7.0.2 | |
| if [ "$UserHomeDir" ] ; then | |
| RemoveItem "$UserHomeDir/Applications/LiveUpdate Folder (OS X)" | |
| RemoveItem "$UserHomeDir/Applications/Norton AntiVirus (OS X)" | |
| RemoveItem "$UserHomeDir/Applications" -e -u | |
| fi | |
| FirefoxExtensions=`find "$UserLibraryDir/Application Support/Firefox/Profiles/"*/extensions/*"@symantec.com.xpi" 2>/dev/null` | |
| for FirefoxExtension in $FirefoxExtensions ; do | |
| RemoveItem "$FirefoxExtension" -u # no longer removed via product uninstaller | |
| done | |
| RemoveItem "$UserLibraryDir/Application Support/Norton" "*" | |
| # If a user directory | |
| if [ "$UserHomeDir" ] ; then | |
| RemoveItem "$UserLibraryDir/Application Support/Symantec" | |
| RemoveItem "$UserHomeDir/Application Support/Symantec" | |
| RemoveItem "$UserHomeDir/Application Support" -E -u | |
| # If .fsd folders should be removed | |
| if $DoRemoveFSDFolders ; then | |
| UserDownloadsDir="$UserHomeDir/Downloads" | |
| # Remove Symantec/Norton installer/package tool apps found within | |
| # user's Downloads folder | |
| InstallerAppsToRemove=" | |
| `find "$UserDownloadsDir" -type d -name "Install Norton*" 2>/dev/null` | |
| `find "$UserDownloadsDir" -type d -name "Install Symantec*" 2>/dev/null` | |
| `find "$UserDownloadsDir" -type d -name "SEP*Redistributable*Installer*Package*Tool*" 2>/dev/null`" | |
| for InstallerAppToRemove in $InstallerAppsToRemove ; do | |
| RemoveItem "$InstallerAppToRemove" -u | |
| done | |
| # Remove any remaining .fsd folders in user's Downloads folder | |
| FSDDirs=`find "$UserDownloadsDir" -type d -name ".fsd" 2>/dev/null` | |
| for FSDDir in $FSDDirs ; do | |
| RemoveItem "$FSDDir" -u | |
| FolderContainingFSDDir=`dirname "$FSDDir"` | |
| # If folder that contained .fsd folder is not the user's Downloads folder | |
| if [ ! "$FolderContainingFSDDir" -ef "$UserDownloadsDir" ] ; then | |
| # Remove the containing folder if it's empty | |
| RemoveItem "$FolderContainingFSDDir" -e -u | |
| fi | |
| done | |
| fi | |
| elif ! $CreateFilesRemovedListOnly ; then | |
| # Make second attempt to remove "/Application Support/Symantec/ErrorReporting" | |
| RemoveItem "$UserLibraryDir/Application Support/Symantec/ErrorReporting" | |
| RemoveItem "$UserLibraryDir/Application Support/Symantec" | |
| fi | |
| RemoveItem "$UserLibraryDir/Documentation/Help/Norton Privacy Control Help" | |
| RemoveItem "$UserLibraryDir/Documentation/Help/Norton Personal Firewall Help" | |
| RemoveItem "$UserLibraryDir/Caches/com.apple.Safari/Extensions/Norton" "*" -u | |
| RemoveItem "$UserLibraryDir/Caches/com.apple.Safari/Extensions/Symantec" "*" -u | |
| RemoveItem "$UserLibraryDir/Caches/com.norton" "*" -u | |
| RemoveItem "$UserLibraryDir/Caches/com.symantec" "*" -u | |
| RemoveItem "$UserLibraryDir/Caches/Norton" "*" -u | |
| RemoveItem "$UserLibraryDir/Caches/Symantec" "*" -u | |
| if $DoRemoveIPUA ; then | |
| # If not a user directory | |
| if [ -z "$UserHomeDir" ] ; then | |
| RemoveItem "$UserLibraryDir/LaunchAgents/com.symantec" "*" | |
| elif $DoRemoveInstallerLaunchAgents ; then | |
| RemoveItem "$UserLibraryDir/LaunchAgents/com.symantec" "*" | |
| else | |
| RemoveItem "$UserLibraryDir/LaunchAgents/com.symantec" "*" -x 'com\.symantec\..*Installer\.plist' | |
| fi | |
| else | |
| # If not a user directory | |
| if [ -z "$UserHomeDir" ] ; then | |
| RemoveItem "$UserLibraryDir/LaunchAgents/com.symantec" "*" -x 'com\.symantec\.ipua\.plist' | |
| elif $DoRemoveInstallerLaunchAgents ; then | |
| RemoveItem "$UserLibraryDir/LaunchAgents/com.symantec" "*" -x 'com\.symantec\.ipua\.plist' | |
| else | |
| RemoveItem "$UserLibraryDir/LaunchAgents/com.symantec" "*" -x 'com\.symantec\..*Installer\.plist' -x 'com\.symantec\.ipua\.plist' | |
| fi | |
| fi | |
| RemoveItem "$UserLibraryDir/Logs/.ipuaint" | |
| RemoveItem "$UserLibraryDir/Logs/.ipualog" | |
| RemoveItem "$UserLibraryDir/Logs/EPMPTestLogs.log" -u | |
| RemoveItem "$UserLibraryDir/Logs/LUTool.txt" | |
| RemoveItem "$UserLibraryDir/Logs/Norton" "*" | |
| RemoveItem "$UserLibraryDir/Logs/o2spy.log" | |
| RemoveItem "$UserLibraryDir/Logs/Symantec" "*" | |
| # RemoveItem "$UserLibraryDir/Logs/Symantec" "*" -u # May need to add this back with refined matching | |
| RemoveItem "$UserLibraryDir/Logs/SymaIpua" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymAPErr.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymAPOut.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymBfw_NFM.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymCommP" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymDebugLeaks.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymDeepsight" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymFWDeepSightTrie.txt" | |
| RemoveItem "$UserLibraryDir/Logs/SymFWLog.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymFWRules.log" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymHTTPSubmissions.txt" | |
| RemoveItem "$UserLibraryDir/Logs/SymInstall" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymIpua" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymMigration.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymOxygen" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymQual" "*" | |
| RemoveItem "$UserLibraryDir/Logs/SymScanServerDaemon.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymSharedSettingsd.log" | |
| RemoveItem "$UserLibraryDir/Logs/SymUninstall" "*" | |
| RemoveItem "$UserLibraryDir/Logs/UIAgent" "*" | |
| RemoveItem "$UserLibraryDir/Preferences/ByHost/com.symantec" "*" | |
| RemoveItem "$UserLibraryDir/Preferences/com.norton" "*" | |
| if $DoRemoveIPUA ; then | |
| RemoveItem "$UserLibraryDir/Preferences/com.symantec" "*" -x 'com\.symantec\.sacm.*' -x 'com\.symantec\.smac.*' | |
| else | |
| RemoveItem "$UserLibraryDir/Preferences/com.symantec" "*" -x 'com\.symantec\.sacm.*' -x 'com\.symantec\.smac.*' -x 'com\.symantec\.ipua\.plist' | |
| fi | |
| RemoveItem "$UserLibraryDir/Preferences/group.com.symantec" "*" -u | |
| RemoveItem "$UserLibraryDir/Preferences/group.symantec" "*" -u | |
| RemoveItem "$UserLibraryDir/Preferences/LiveUpdate Preferences" | |
| RemoveItem "$UserLibraryDir/Preferences/LU Admin Preferences" | |
| RemoveItem "$UserLibraryDir/Preferences/LU Host Admin.plist" | |
| RemoveItem "$UserLibraryDir/Preferences/NAV8.0.003.plist" | |
| RemoveItem "$UserLibraryDir/Preferences/Network/com.symantec" "*" | |
| RemoveItem "$UserLibraryDir/Preferences/Norton AntiVirus Prefs Folder" | |
| RemoveItem "$UserLibraryDir/Preferences/Norton Application Aliases" | |
| RemoveItem "$UserLibraryDir/Preferences/Norton Personal Firewall Log" | |
| RemoveItem "$UserLibraryDir/Preferences/Norton Scheduler OS X.plist" | |
| RemoveItem "$UserLibraryDir/Preferences/Norton Utilities Preferences" | |
| RemoveItem "$UserLibraryDir/Preferences/Norton Zone" | |
| RemoveItem "$UserLibraryDir/Preferences/wcid" | |
| RemoveItem "$UserLibraryDir/Safari/Extensions/Norton" "*" -u | |
| RemoveItem "$UserLibraryDir/Safari/Extensions/Symantec" "*" -u | |
| RemoveItem "$UserLibraryDir/Saved Application State/com.symantec" "*" -u | |
| done | |
| } | |
| RemoveInvisibleFilesFromVolume() | |
| { | |
| # Usage: RemoveInvisibleFilesFromVolume $1 | |
| # Argument: $1 = Volume name. The name should begin with "/Volumes/" | |
| # unless it is "/" (boot volume). | |
| # Summary: Removes the invisible Symantec for OS X files - Symantec FS | |
| # and AntiVirus QuickScan files - from $1. | |
| # | |
| ! $RemoveInvisibleFiles && return | |
| CurrentVolumeBeingUsed="$1" | |
| cd "$1" | |
| if $CreateFilesRemovedListOnly ; then | |
| $DoShowOnlyFilesThatShouldHaveBeenUninstalled || echo "Finding invisible Symantec files on: $1" >&2 | |
| elif $ShowFilesAsRemoved ; then | |
| echo "Locating invisible Symantec files in: $1" | |
| else | |
| echo "Removing invisible Symantec files from: $1" | |
| fi | |
| RemoveItem "/.SymAVQSFile" | |
| RemoveItem "/NAVMac800QSFile" | |
| RemoveItem "/Norton FS Data" | |
| RemoveItem "/Norton FS Index" | |
| RemoveItem "/Norton FS Volume" | |
| RemoveItem "/Norton FS Volume 2" | |
| } | |
| RemoveItem() | |
| { | |
| # Usage: RemoveItem ["private_was_added"] FilePath [-d] [-e | -E] [-u] [-x <pattern>] [FileExtension] | |
| # | |
| # Summary: Deletes the file or folder passed, FilePath, from the | |
| # current directory. FilePath should be full path beginning | |
| # with /. | |
| # | |
| # Options: | |
| # -d Treat FilePath as a directory in which to match FileExtension | |
| # or when using the -x option. See FileExtension and -x option | |
| # below. The -d must be passed prior to passing the -x option. | |
| # FilePath itself will not be deleted, only the matching items | |
| # within it will be deleted. If no FileExtension is passed, "*" | |
| # is assumed. | |
| # -e Delete FilePath only if it is a directory that is empty or | |
| # that contains only ".DS_Store" and/or ".localized" files. | |
| # If the folder could not be deleted, error message is shown. | |
| # -E Same as the -e option, except no error message is shown if | |
| # the folder could not be deleted. | |
| # -u Item is not removed by Symantec Uninstaller.app. | |
| # -x <Pattern> | |
| # Pattern to exclude from file list. Pattern will become | |
| # ^FilePathPattern$ (or ^FilePath/Pattern$ if -d was passed | |
| # before -x was passed) so add wildcards as needed. Make sure | |
| # to prefix special characters you wish to match with \ | |
| # (example: to match a period, \.). You may pass several | |
| # -x <pattern> groupings. Pattern is an extended regular | |
| # expression. Letter case is ignored. | |
| # <FileExtension> | |
| # All files are deleted that match FilePath.*FileExtension or | |
| # if -d was passed that match FilePath/.*FileExtension. | |
| # To match any files that begin with FilePath, pass "*" as | |
| # FileExtension (don't pass * unquoted). Only the last | |
| # FileExtension passed will be used. Periods will be escaped | |
| # (i.e., each . will become \.). | |
| # "private_was_added" | |
| # This gets passed as the first argument by RemoveItem() when | |
| # FilePath is a link in PrivateLinksPattern. This option is | |
| # only to be passed by RemoveItem() itself. | |
| # | |
| # Note: Make sure to run the SetupCleanup function before the | |
| # first run of this function and run the FinishCleanup | |
| # function before exiting the script. | |
| # | |
| # Make sure to change directory to root of the volume you | |
| # want the file or folder removed from before calling this | |
| # function. | |
| # | |
| # FilePath must be the first argument unless "private_was_added" | |
| # was passed as the first. The other options may appear after | |
| # FilePath in any order. | |
| # | |
| local ExclusionPattern="" | |
| local FilePath="$1" | |
| shift | |
| # If / or no file name passed | |
| if [ "z$FilePath" = z/ -o -z "$FilePath" ] ; then | |
| return | |
| # Else if this is a call by RemoveItem() with /private added to original path | |
| elif [ "z$FilePath" = zprivate_was_added ] ; then | |
| FilePath="$1" | |
| shift | |
| # Else if original path begins with /private/ and is targeted by a link in / | |
| elif [ "`echo "$FilePath" | egrep -e "$PrivateDirectoriesPattern"`" ] ; then | |
| # Remove /private from beginning of path | |
| FilePath=`echo "$FilePath" | awk '{print substr($0,9)}'` | |
| fi | |
| VolumeFromWhichToRemove="`pwd`" | |
| # If path passed begins with /etc/, /tmp/, or /var/ | |
| if [ "`echo "$FilePath" | egrep -e "$PrivateLinksPattern"`" ] ; then | |
| PrivateLinkName=`echo "$FilePath" | awk -F / '{print $2}'` | |
| PrivateLinkRoot="$VolumeFromWhichToRemove/$PrivateLinkName" | |
| PrivateDirRoot="$VolumeFromWhichToRemove/private/$PrivateLinkName" | |
| # If path does not point to the same file as "/private/" + path | |
| if [ ! "$PrivateLinkRoot" -ef "$PrivateDirRoot" ] ; then | |
| FilePathOriginal="$FilePath" | |
| # Attempt to remove path from within /private first | |
| RemoveItem "private_was_added" "/private$FilePath" "$@" | |
| # Then attempt to remove path itself | |
| FilePath="$FilePathOriginal" | |
| fi | |
| fi | |
| if [ "$VolumeFromWhichToRemove" = "/" ] ; then | |
| FullFilePath="$FilePath" | |
| else | |
| FullFilePath="$VolumeFromWhichToRemove$FilePath" | |
| fi | |
| # If logs should not be removed | |
| if ! $DoRemoveLogs ; then | |
| # If file path contains "/Library/Logs/", skip removal | |
| if [ "`echo "$FullFilePath" | egrep '/Library/Logs/'`" ] ; then | |
| return | |
| fi | |
| fi | |
| PathDir=`dirname "$FullFilePath"` | |
| [ -z "$PathDir" ] && return | |
| # Set PathBasePattern = basename of path with each . translated to \. | |
| PathBasePattern=`basename "$FullFilePath" | sed s/"\."/"\\\\\."/g` | |
| [ -z "$PathBasePattern" ] && return | |
| DeleteOnlyIfEmptyDir=false | |
| ExtensionPassed="" | |
| PathIsDirectory=false | |
| SkipErrorMessageIfEmptyDirNotFound=false | |
| ShouldNotBeRemovedBySymantecUninstaller=false | |
| while [ "$1" ] ; do | |
| case "$1" in | |
| -d) | |
| PathDir="$FullFilePath" | |
| PathBasePattern="" | |
| PathIsDirectory=true | |
| ;; | |
| -e) | |
| DeleteOnlyIfEmptyDir=true | |
| SkipErrorMessageIfEmptyDirNotFound=false | |
| ;; | |
| -E) | |
| DeleteOnlyIfEmptyDir=true | |
| SkipErrorMessageIfEmptyDirNotFound=true | |
| ;; | |
| -u) | |
| ShouldNotBeRemovedBySymantecUninstaller=true | |
| ;; | |
| -x) | |
| if [ "$2" ] ; then | |
| shift | |
| if [ "$ExclusionPattern" ] ; then | |
| ExclusionPattern="$ExclusionPattern|^$PathDir/$1$" | |
| else | |
| ExclusionPattern="^$PathDir/$1$" | |
| fi | |
| fi | |
| ;; | |
| *) | |
| ExtensionPassed="$1" | |
| ;; | |
| esac | |
| shift | |
| done | |
| if [ "z$ExtensionPassed" = "z*" ] ; then | |
| ListOfPaths=`find "$PathDir" -mindepth 1 -maxdepth 1 2>/dev/null | grep -i "^$PathDir/$PathBasePattern" | sort -f` | |
| PathToShow="$FullFilePath`$PathIsDirectory && echo /`*" | |
| elif [ "$ExtensionPassed" ] ; then | |
| ExtensionPassedPattern=`printf "%s" "$ExtensionPassed" | sed s/"\."/"\\\\\."/g` | |
| ListOfPaths=`find "$PathDir" -mindepth 1 -maxdepth 1 2>/dev/null | grep -i "^$PathDir/$PathBasePattern.*$ExtensionPassedPattern$" | sort -f` | |
| PathToShow="$FullFilePath*$ExtensionPassed" | |
| elif $PathIsDirectory ; then | |
| ListOfPaths=`find "$FullFilePath" -mindepth 1 -maxdepth 1 2>/dev/null | sort -f` | |
| PathToShow="$FullFilePath/*" | |
| else | |
| ListOfPaths=`ls -d "$FullFilePath" 2>/dev/null` | |
| PathToShow="$FullFilePath" | |
| fi | |
| # If there are items to exclude from the list and there are matching items | |
| if [ "z$ExclusionPattern" != z -a -n "$ListOfPaths" ] ; then | |
| ListOfPaths=`printf "%s" "$ListOfPaths" | egrep -i -v -e "$ExclusionPattern"` | |
| fi | |
| if $CreateFilesRemovedListOnly ; then | |
| # If -E passed, then don't list the item | |
| $SkipErrorMessageIfEmptyDirNotFound && return | |
| if ! $ListOnlyFilesThatExist ; then | |
| echo "$PathToShow`$DeleteOnlyIfEmptyDir && echo " [folder deleted only if empty]"`" >> "$FilesRemovedList" | |
| # Else if file exists | |
| elif [ "$ListOfPaths" ] ; then | |
| ItemsToAddToList="" | |
| IFS=' | |
| ' | |
| if $DeleteOnlyIfEmptyDir ; then | |
| $ShowOnlyRegularFiles || ItemsToAddToList="$ListOfPaths" | |
| else | |
| for EachItemListed in $ListOfPaths ; do | |
| if [ -f "$EachItemListed" ] ; then | |
| ItemsToAddToList="$ItemsToAddToList | |
| $EachItemListed" | |
| elif [ -L "$EachItemListed" -a $ShowOnlyRegularFiles = false ] ; then | |
| ItemsToAddToList="$ItemsToAddToList | |
| $EachItemListed" | |
| else | |
| ItemsToAddToList="$ItemsToAddToList | |
| `find "$EachItemListed" $FindOption1 $FindOption2 2>/dev/null`" | |
| fi | |
| done | |
| fi | |
| for EachItemFound in $ItemsToAddToList ; do | |
| if $ShouldNotBeRemovedBySymantecUninstaller ; then | |
| AddedText="$NotRemovedBySymantecUninstallerText" | |
| elif [ "`echo "$EachItemFound" | grep -F "$NotRemovedByNIS6Uninstaller"`" ] ; then | |
| AddedText="$NotRemovedByNIS6UninstallerText" | |
| elif [ "`echo "$EachItemFound" | grep -F "$NotRemovedBySymantecUninstallerPattern"`" ] ; then | |
| AddedText="$NotRemovedBySymantecUninstallerText" | |
| else | |
| AddedText="" | |
| fi | |
| if $ShowOnlyRegularFiles ; then | |
| # If would be an empty folder or would not be removed by Symantec Uninstaller, don't add item to the list | |
| [ $DeleteOnlyIfEmptyDir = true -o -n "$AddedText" ] && continue | |
| fi | |
| echo "$EachItemFound`$DeleteOnlyIfEmptyDir && echo " [folder deleted only if empty]"`$AddedText" >> "$FilesRemovedFilesOnlyList" | |
| done | |
| NoFilesToRemove=false | |
| FilesFoundOnThisVolume=true | |
| fi | |
| return | |
| fi | |
| IFS=' | |
| ' | |
| for EachFullPath in $ListOfPaths ; do | |
| # If -e or -E was passed | |
| if $DeleteOnlyIfEmptyDir ; then | |
| # remove directory only if empty | |
| RemoveEmptyDirectory "$EachFullPath" | |
| # If -E passed, then skip error reporting | |
| $SkipErrorMessageIfEmptyDirNotFound && continue | |
| else | |
| $ShowFilesAsRemoved && echo " Removing: \"$EachFullPath\"" | |
| # Clear immutable bit to remove any Finder lock | |
| chflags -R nouchg "$EachFullPath" 2>/dev/null 1>&2 | |
| BackupLog "$EachFullPath" | |
| /bin/rm -rf "$EachFullPath" 2>/dev/null 1>&2 # Remove file/folder | |
| fi | |
| # If file still exists | |
| if [ "`ls -d "$EachFullPath" 2>/dev/null`" ] ; then | |
| TheFileWasRemoved=false | |
| else | |
| TheFileWasRemoved=true | |
| SomeFileWasRemoved=true | |
| fi | |
| # If the file/folder was not removed | |
| if ! $TheFileWasRemoved ; then | |
| if ! $ErrorOccurred ; then | |
| # Create LogFile | |
| echo "Symantec files/folders not removed:" >"$LogFile" | |
| chmod a=rw "$LogFile" | |
| ErrorOccurred=true | |
| fi | |
| echo " $EachFullPath" >>"$LogFile" | |
| # Else if boot volume | |
| elif [ "$CurrentVolumeBeingUsed" = "/" ] ; then | |
| RestartMayBeNeeded=true | |
| # If it's not a file that does not require a restart (Etrack 3925328) | |
| if [ -z "`printf "%s" "$EachFullPath" | egrep -ie "$FilesThatDoNotRequireRebootPattern"`" ] ; then | |
| touch "$SymantecCleanupRestartFile" | |
| fi | |
| SomeFileWasRemovedFromBootVolume=true | |
| else | |
| SomeFileWasRemovedFromNonBootVolume=true | |
| fi | |
| NoFilesToRemove=false | |
| FilesFoundOnThisVolume=true | |
| done | |
| } | |
| RemoveLoginKeychainPasswords() | |
| { | |
| # Usage: RemoveLoginKeychainPasswords volume | |
| # Summary: Removes items from login keychains. | |
| # If volume is not / (current boot volume), removal is skipped. | |
| # If volume is not specified, / is assumed. | |
| # | |
| local VolumeBeingPurged="$1" | |
| local ComputerUserEntry | |
| local EachLoginKeychain | |
| local HelpTextToShow | |
| local LoginKeychainPasswordToDelete | |
| local LoginKeychainPasswordToDeleteLine | |
| local UserDir | |
| local UserOfKeychain | |
| # If volume not specified, assume it is boot volume | |
| [ -z "$VolumeBeingPurged" ] && VolumeBeingPurged=/ | |
| # If volume being cleaned up is not the boot volume, skip purge | |
| [ "z$VolumeBeingPurged" != z/ ] && return | |
| $DoShowOnlyFilesThatShouldHaveBeenUninstalled || echo "Looking for Symantec login keychain items" 2>/dev/null | |
| IFS=' | |
| ' | |
| for ComputerUserEntry in $ComputerUsersTable ; do | |
| UserOfKeychain=`echo "$ComputerUserEntry" | awk -F ' ' '{print $1}'` | |
| UserDir=`echo "$ComputerUserEntry" | awk -F ' ' '{print $2}'` | |
| EachLoginKeychain="$UserDir/Library/Keychains/login.keychain" | |
| [ ! -f "$EachLoginKeychain" ] && continue | |
| for LoginKeychainPasswordToDeleteLine in $LoginKeychainPasswordsToDelete ; do | |
| LoginKeychainPasswordToDelete=`echo "$LoginKeychainPasswordToDeleteLine" | awk -F ' ' '{print $1}'` | |
| HelpTextToShow=`echo "$LoginKeychainPasswordToDeleteLine" | awk -F ' ' '{print $2}'` | |
| /usr/bin/security find-generic-password -s "$LoginKeychainPasswordToDelete" "$EachLoginKeychain" 2>/dev/null 1>&2 | |
| if [ $? = 0 ] ; then | |
| if $CreateFilesRemovedListOnly ; then | |
| echo "$HelpTextToShow ($LoginKeychainPasswordToDelete) would be removed" >> "$FilesRemovedList" | |
| echo "from $UserOfKeychain's login keychain" >> "$FilesRemovedList" | |
| echo "" >> "$FilesRemovedList" | |
| else | |
| echo "Removing $HelpTextToShow ($LoginKeychainPasswordToDelete)" | |
| echo "from $UserOfKeychain's login keychain" | |
| /usr/bin/security delete-generic-password -s "$LoginKeychainPasswordToDelete" "$EachLoginKeychain" 2>/dev/null 1>&2 | |
| fi | |
| fi | |
| done | |
| done | |
| } | |
| RemoveNortonZoneDirectories() | |
| { | |
| # Usage: RemoveNortonZoneDirectories user_home_directory | |
| # Summary: Removes Norton Zone paths listed in zoneDirectoryManagerRegistryKey in | |
| # user_home_directory/Preference/com.symantec.nds.Norton-Zone.plist | |
| # | |
| local UserHomeDir="$1" | |
| local ZonePath | |
| local ZonePaths | |
| [ ! -d "$UserHomeDir" ] && return | |
| ZonePaths=`defaults read "$UserHomeDir/Library/Preferences/"com.symantec.nds.Norton-Zone zoneDirectoryManagerRegistryKey 2>/dev/null | grep = | awk -F '"' '{print $2}'` | |
| IFS=' | |
| ' | |
| for ZonePath in $ZonePaths ; do | |
| RemoveItem "$ZonePath" | |
| done | |
| RemoveItem "$UserHomeDir/Norton Zone" "*" | |
| } | |
| RestartComputer() | |
| { | |
| # Usage: RestartComputer | |
| # Summary: Prompts to see if user would like to restart. Restarts | |
| # computer using 'reboot' command if 'yes' or 'y' is | |
| # entered; exits the script otherwise. | |
| # Note: User must be root or an admin for reboot to work, so this | |
| # function should only be used in scripts run as root or | |
| # admin user. OSXmajorVersion should be defined prior to | |
| # calling this function. | |
| # | |
| echo | |
| # If OSXmajorVersion is not a number | |
| if [ -z "`expr "$OSXmajorVersion" / 1 2>/dev/null`" ] ; then | |
| # Assume that osascript can be used to restart the computer - osascript | |
| # in OS 10.2 and later provided restart option for system events | |
| OSXmajorVersion=2 | |
| fi | |
| if $RunningFromWithinAppBundleOrSupportFolder ; then | |
| ExitScript $FinishedExitCode | |
| elif $QuitWithoutRestarting ; then | |
| echo "Exited the script without restarting the computer." | |
| ExitScript $FinishedExitCode | |
| elif ! $RestartAutomatically ; then | |
| # If OS version is less that 10.2 | |
| CompareMacOSVersion 10 2 | |
| if [ $? -eq 255 ] ; then | |
| echo "Do you wish to restart the computer now (WARNING: Unsaved changes" | |
| printf "in other open applications will be lost if you do!) (y/n)? " | |
| else | |
| printf "Do you wish to restart the computer now (y/n)? " | |
| fi | |
| if `YesEntered` ; then | |
| RestartAutomatically=true | |
| fi | |
| echo | |
| fi | |
| if $RestartAutomatically ; then | |
| if $PauseBeforeRestarting ; then | |
| printf "Computer will restart in 3 seconds (ctrl-C to cancel restart)..." | |
| sleep 1 &>/dev/null | |
| printf " 3" | |
| sleep 1 &>/dev/null | |
| printf " 2" | |
| sleep 1 &>/dev/null | |
| printf " 1" | |
| sleep 1 &>/dev/null | |
| echo | |
| fi | |
| echo | |
| echo "Restarting the computer..." | |
| # If OS version is less that 10.2 | |
| CompareMacOSVersion 10 2 | |
| if [ $? -eq 255 ] ; then | |
| reboot | |
| else | |
| osascript -e 'tell application "System Events" to restart' | |
| fi | |
| else | |
| echo "Exited the script without restarting the computer." | |
| fi | |
| ExitScript $FinishedExitCode | |
| } | |
| RunPredeleteScripts() | |
| { | |
| # Usage: RunPredeleteScripts [$1] | |
| # Argument: $1 = Path of current volume. | |
| # Summary: If $1 is "" or /, predelete scripts in receipts listed in | |
| # ReceiptsTable are run. | |
| # | |
| RunPredeleteScript() | |
| { | |
| local OptionToPassToPredelete="" | |
| local PredeleteScriptProgram | |
| if [ -x "$PredeleteScript" ] ; then | |
| echo "--- Running $PredeleteScript ---" | |
| export SYMANTEC_SAVED_DATA_DIR | |
| echo ">>>>>>>>>>>> Predelete run BEGAN at: `date +"%Y-%m-%d %H:%M:%S"` <<<<<<<<<<<<" | |
| # If predelete script processes --skip-symquald as an option | |
| if [ "`grep -e "--skip-symquald" "$PredeleteScript"`" ] ; then | |
| # Pass --skip-symquald to the predelete script to skip symquald submission | |
| OptionToPassToPredelete="--skip-symquald" | |
| fi | |
| if $ShowPredeleteErrors ; then | |
| PredeleteScriptProgram=`head -n 1 "$PredeleteScript" | grep '^#!'` | |
| PredeleteScriptProgram=`basename "$PredeleteScriptProgram"` | |
| # If predelete script is a bash or sh script | |
| if [ "z$PredeleteScriptProgram" = zbash -o "z$PredeleteScriptProgram" = zsh ] ; then | |
| # Pass -vx to script interpreter to show verbose output | |
| echo "$PredeleteScriptProgram -vx \"$PredeleteScript\"" $OptionToPassToPredelete | |
| "$PredeleteScriptProgram" -vx "$PredeleteScript" $OptionToPassToPredelete | |
| else | |
| echo "$PredeleteScript $OptionToPassToPredelete" | |
| "$PredeleteScript" $OptionToPassToPredelete | |
| fi | |
| else | |
| "$PredeleteScript" $OptionToPassToPredelete 2>/dev/null 1>&2 | |
| fi | |
| echo "Predelete script exited with $?" | |
| echo ">>>>>>>>>>>> Predelete run ENDED at: `date +"%Y-%m-%d %H:%M:%S"` <<<<<<<<<<<<" | |
| fi | |
| } | |
| local EachReceiptLine | |
| local EachReceiptMatchingAll | |
| local ReceiptList | |
| local ReceiptListMatchingAll="" | |
| local VolumePathPassed="$1" | |
| [ "z$VolumePathPassed" = z/ ] && VolumePathPassed="" | |
| if $CreateFilesRemovedListOnly ; then | |
| if [ "$VolumePathPassed" ] ; then | |
| echo "Receipt predelete scripts would not be run on that volume." >> "$FilesRemovedList" | |
| elif $DoRunPredeleteScripts ; then | |
| echo "Receipt predelete scripts would be run as they are found." >> "$FilesRemovedList" | |
| else | |
| echo "Receipt predelete scripts would not be run because the -d option was specified." >> "$FilesRemovedList" | |
| fi | |
| return | |
| elif [ "$VolumePathPassed" ] ; then | |
| echo "Receipt predelete scripts were not run on that volume." | |
| return | |
| elif ! $DoRunPredeleteScripts ; then | |
| echo "Receipt predelete scripts were not run because the -d option was specified." | |
| return | |
| fi | |
| SYMANTEC_SAVED_DATA_DIR="/private/tmp/$FullScriptName-SYMANTEC_SAVED_DATA_DIR-`date +"%Y%m%d%H%M%S"`" | |
| mkdir -p "$SYMANTEC_SAVED_DATA_DIR" 2>/dev/null | |
| IFS=' | |
| ' | |
| echo "Looking for predelete scripts in Symantec uninstaller's Receipts folder" | |
| for PredeleteScript in `find "/Library/Application Support/Symantec/Uninstaller" 2>/dev/null | grep -E 'predelete$|pre_delete$'` ; do | |
| RunPredeleteScript | |
| done | |
| echo "Looking for predelete scripts in /Library/Receipts" | |
| ReceiptList=`echo "$ReceiptsTable" | grep '\.pkg' | grep -v '^#'` | |
| for EachReceiptMatchingAll in `echo "$ReceiptsTable" | grep ' -a' | grep -v '^#' | awk -F ' ' '{print $1}'` ; do | |
| ReceiptListMatchingAll="$ReceiptListMatchingAll | |
| `ls -d "/Library/Receipts/$EachReceiptMatchingAll"* 2>/dev/null`" | |
| done | |
| for EachReceiptMatchingAll in $ReceiptListMatchingAll ; do | |
| ReceiptList="$ReceiptList | |
| `basename "$EachReceiptMatchingAll"`" | |
| done | |
| for EachReceiptLine in $ReceiptList ; do | |
| ReceiptArg=`echo "$EachReceiptLine" | awk -F " " '{print $2}'` | |
| [ "z$ReceiptArg" = z-s ] && continue | |
| ReceiptName=`echo "$EachReceiptLine" | awk -F " " '{print $1}'` | |
| [ -z "`echo "$ReceiptName" | grep '\.pkg$'`" ] && continue | |
| if [ -d "/Library/Receipts/$ReceiptName" ] ; then | |
| for PredeleteScript in `find "/Library/Receipts/$ReceiptName" 2>/dev/null | grep -E 'predelete$|pre_delete$'` ; do | |
| RunPredeleteScript | |
| done | |
| fi | |
| ReceiptName="`basename "$ReceiptName" .pkg`Dev.pkg" | |
| if [ -d "/Library/Receipts/$ReceiptName" ] ; then | |
| for PredeleteScript in `find "/Library/Receipts/$ReceiptName" 2>/dev/null | grep -E 'predelete$|pre_delete$'` ; do | |
| RunPredeleteScript | |
| done | |
| fi | |
| done | |
| rm -rf "$SYMANTEC_SAVED_DATA_DIR" 2>/dev/null | |
| } | |
| SetupCleanup() | |
| { | |
| # Usage: SetupCleanup | |
| # Summary: Initializes variables needed for the RemoveItem function. | |
| # | |
| BackupLogLocationDir="$BackupLogLocationRootDir/`date +"%Y-%m-%d_%H-%M-%S"`" | |
| ErrorOccurred=false | |
| NoFilesToRemove=true | |
| /bin/rm -rf "$FilesRemovedList" "$FilesRemovedFilesOnlyList" 2>/dev/null 1>&2 | |
| if $CreateFilesRemovedListOnly ; then | |
| if $ListOnlyFilesThatExist ; then | |
| echo "Summary of what $FullScriptName would do, based on files" > "$FilesRemovedList" | |
| echo "`$RemoveCrontabEntries && echo "and crontab entries "`that currently exist:" >> "$FilesRemovedList" | |
| else | |
| echo "Summary of what $FullScriptName would attempt to do:" > "$FilesRemovedList" | |
| fi | |
| fi | |
| } | |
| ShowContents() | |
| { | |
| # Usage1: ShowContents [-c] [-w] File [TextToShow] | |
| # Usage2: ShowContents [-c] [-w] -s String [TextToShow] | |
| # Summary: Displays contents of File or String. If there are more than | |
| # $LINES or 23 lines, more command is used, using TextToShow as | |
| # the name of the file; if TextToShow is not passed, "....." is | |
| # used. If -c is specified, screen is cleared beforehand. | |
| # If -w is specified, then width of strings will be factored | |
| # into the line count (this option makes output slower when | |
| # the number of lines is less than $LINES or 23). | |
| # | |
| local SCLineCount | |
| local SCCurrentDir | |
| local SCTempFolder | |
| local SCTempFile | |
| local SCColumns | |
| local SCColumnsMax | |
| local SCColumnsMaxDefault=80 | |
| local SCColumnsRemainder | |
| local CSDoAdjustForWidth=false | |
| local CSDoUseString=false | |
| local SCEachLine | |
| local SCGrepPattern='.' | |
| local SCLineFactor | |
| local SCLines | |
| local SCLinesMax | |
| local SCLinesMaxDefault=23 | |
| local SCText | |
| while [ "$1" ] ; do | |
| if [ "z$1" = z-c ] ; then | |
| clear | |
| elif [ "z$1" = z-s ] ; then | |
| CSDoUseString=true | |
| elif [ "z$1" = z-w ] ; then | |
| CSDoAdjustForWidth=true | |
| else | |
| break | |
| fi | |
| shift | |
| done | |
| [ "$COLUMNS" ] && SCColumnsMax=`expr "$COLUMNS" - 0 2>/dev/null` | |
| [ -z "$SCColumnsMax" ] && SCColumnsMax=$SCColumnsMaxDefault | |
| [ "$LINES" ] && SCLinesMax=`expr "$LINES" - 1 2>/dev/null` | |
| [ -z "$SCLinesMax" ] && SCLinesMax=$SCLinesMaxDefault | |
| [ $SCColumnsMax -ge $SCColumnsMaxDefault ] && SCGrepPattern='.................................................................................' | |
| if $CSDoUseString ; then | |
| SCLineCount=`printf "%s\n" "$1" | grep -c ""` | |
| $CSDoAdjustForWidth && SCText=`printf "%s\n" "$1" | grep "$SCGrepPattern"` | |
| elif [ -f "$1" ] ; then | |
| SCLineCount=`grep -c "" "$1"` | |
| $CSDoAdjustForWidth && SCText=`grep "$SCGrepPattern" "$1"` | |
| else | |
| return 1 | |
| fi | |
| if $CSDoAdjustForWidth ; then | |
| if [ $SCLineCount -le $SCLinesMax ] ; then | |
| IFS=' | |
| ' | |
| for SCColumns in `printf "%s" "$SCText" | awk '{print length($0)}'` ; do | |
| [ $SCLineCount -gt $SCLinesMax ] && break | |
| SCLineFactor=`expr $SCColumns / $SCColumnsMax` | |
| [ `expr $SCColumns % $SCColumnsMax` -gt 0 ] && let SCLineFactor=$SCLineFactor+1 | |
| [ $SCLineFactor -gt 1 ] && let SCLineCount=$SCLineCount+$SCLineFactor-1 | |
| done | |
| fi | |
| fi | |
| if $CSDoUseString ; then | |
| if [ $SCLineCount -gt $SCLinesMax ] ; then | |
| SCCurrentDir=`pwd` | |
| SCTempFolder="/private/tmp/$FullScriptName-SC-`date +"%Y%m%d%H%M%S"`" | |
| mkdir "$SCTempFolder" 2>/dev/null | |
| [ ! -d "$SCTempFolder" ] && return 1 | |
| cd "$SCTempFolder" 2>/dev/null | |
| [ "$2" ] && SCTempFile="$2" || SCTempFile="....." | |
| printf "%s\n" "$1" >"$SCTempFile" | |
| more -E "$SCTempFile" | |
| cd "$SCCurrentDir" 2>/dev/null | |
| rm -rf "$SCTempFolder" 2>/dev/null | |
| else | |
| printf "%s\n" "$1" | |
| fi | |
| elif [ -f "$1" ] ; then | |
| if [ $SCLineCount -gt $SCLinesMax ] ; then | |
| SCCurrentDir=`pwd` | |
| SCTempFolder="/private/tmp/$FullScriptName-SC-`date +"%Y%m%d%H%M%S"`" | |
| mkdir "$SCTempFolder" 2>/dev/null | |
| [ ! -d "$SCTempFolder" ] && return 1 | |
| [ "$2" ] && SCTempFile="$2" || SCTempFile="....." | |
| cat "$1" >"$SCTempFolder/$SCTempFile" | |
| cd "$SCTempFolder" 2>/dev/null | |
| more -E "$SCTempFile" | |
| cd "$SCCurrentDir" 2>/dev/null | |
| rm -rf "$SCTempFolder" 2>/dev/null | |
| else | |
| cat "$1" | |
| fi | |
| fi | |
| return 0 | |
| } | |
| 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 <Path> | |
| # 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. | |
| # | |
| TEMPFILETEMPLATE="/private/tmp/SymantecTemp" | |
| TEMPFILE="$TEMPFILETEMPLATE`date +"%Y%m%d%H%M%S"`-1" | |
| ShowVersion >>"$TEMPFILE" | |
| $AutoRunScript && echo " | |
| Note: This script requires no user interaction if run as root. You can | |
| run this script on several machines at once by using Symantec | |
| Endpoint Protection to push this script to client Macs." >>"$TEMPFILE" | |
| echo " | |
| WARNING: This script will remove all files and folders created by Symantec | |
| Mac OS X products any files within those folders. Therefore, you will | |
| lose ALL files that reside in those folders, including any that you | |
| have created. | |
| Usage: $FullScriptName [-CcdeFfghIikLlmpQqRrV] [-QQ] [-re] [volume ...] | |
| Summary: If no option or volume is specified, then all Symantec files are | |
| removed from the current boot volume, including the invisible | |
| Symantec files (i.e., AntiVirus QuickScan and Symantec FS files), | |
| and Symantec crontab entries are removed from all users' crontabs; | |
| otherwise, for each volume specified, all Symantec files and | |
| Symantec crontab entries will be removed from that volume if no | |
| options are specified. If files are removed from the current boot | |
| volume, receipt predelete scripts are run unless -d is passsed | |
| and Symantec processes are killed unless -k is passed. | |
| If a volume does not have OS X installed on it, then only the | |
| invisible Symantec files are removed from that volume. | |
| Each volume name may begin with \"/Volumes/\", unless it is \"/\". | |
| The easiest way to specify a volume is to drag the volume onto the | |
| Terminal window. | |
| Note: The Terminal application does not support high ASCII or | |
| double-byte character entry via keyboard or via drag-and-drop. | |
| If you want to have files removed from a volume that is not | |
| the current boot volume and that has a name containing high | |
| ASCII or double-byte characters, use the -A option. | |
| Options: -A Remove all Symantec files from all mounted volumes. | |
| Crontab entries are also removed from the current boot | |
| volume, but not from other volumes. If a volume does not | |
| have OS X installed on it, then only the invisible Symantec | |
| files are removed from that volume. | |
| -C Do not remove crontab entries. | |
| -c Only remove crontab entries from all users' crontabs. | |
| Nothing is removed from any volume. | |
| -d Bypass the running of receipt predelete scripts. It is best | |
| to have predelete scripts run for more thorough uninstalls. | |
| -E Suppress errors and other output when predelete scripts are run. | |
| Predelete scripts are run only when removing files from the | |
| current boot volume. | |
| -e Show errors and other output when predelete scripts are run. | |
| Predelete scripts are run only when removing files from the | |
| current boot volume. This is the default as of verion 7.0.73. | |
| -F List only regular files that are currently installed and | |
| that would be deleted. No note is added if a file is not | |
| supposed to be removed by product uninstaller. | |
| -f Do not show files as they are removed. If -f is not | |
| specified, file names are shown as files are removed. | |
| -g Do not remove items located within: | |
| /Library/Logs | |
| {each user's home}/Library/Logs | |
| -h Display help. | |
| -I Do not remove invisible Symantec files. | |
| -i Only remove invisible Symantec files. | |
| -k Do not attempt to kill Symantec processes. | |
| -l List only files that are currently installed and that | |
| would be deleted. As of version 6.0.0, contents of folders | |
| are also shown. Nothing is deleted by this option. | |
| -L List all files that $FullScriptName will attempt | |
| to find and delete. Nothing is deleted by this option. | |
| -m Show output from -l, -L, or -R options using more program. | |
| This is no longer the default action as of version 5.52 | |
| of $FullScriptName. | |
| -p Eliminate pause before restarting computer. If option -p | |
| is not specified, then there is a three second delay | |
| before the restart occurs. | |
| -q Quit script without restarting. This also suppresses | |
| the prompt to restart. | |
| -Q Quits Terminal application when script is done. If | |
| Terminal is being run by more than one user at once, | |
| Terminal is not quit. If passed a second time, it is | |
| the same as -QQ option. | |
| -QQ Quits Terminal application for all users when script is | |
| done. | |
| -R This option is equivalent to the -l option. | |
| -r Automatically restart computer when script is done if | |
| there are Symantec processes and/or kexts in memory and | |
| there were non-invisible files removed from /. | |
| -re Same as -r option. Though -re is deprecated, it remains | |
| for backwards compatibility. | |
| -u Only output files that are installed that should have been | |
| removed by the UI uninstaller. If there are files found, | |
| exit with $ExitCodeWhenFilesRemain; otherwise, exit with 0. No progress is shown | |
| and nothing is deleted. | |
| -S Remove files only for SEP product | |
| -V Show version only. | |
| Examples: | |
| $FullScriptName | |
| Deletes all Symantec files and Symantec crontab entries | |
| from the boot volume. | |
| $FullScriptName /Volumes/OS\ 10.2 | |
| Deletes all Symantec files and Symantec crontab entries | |
| from the volume named \"OS 10.2\". | |
| Nothing is deleted from the boot volume. | |
| $FullScriptName Runner / | |
| Deletes all Symantec files and Symantec crontab entries | |
| from the volume named \"Runner\" and from the boot volume. | |
| $FullScriptName -i \"Test Disk\" | |
| Deletes only invisible Symantec files from the volume named | |
| \"Test Disk\". | |
| $FullScriptName -A -r | |
| Deletes all Symantec files and Symantec crontab entries | |
| from all mounted volumes that have OS X installed on them. | |
| Deletes only invisible Symantec files from volumes that do | |
| not have OS X installed on them. | |
| Computer is restarted automatically if necessary. | |
| $FullScriptName -Ai | |
| Deletes only invisible Symantec files from all volumes. | |
| $FullScriptName -I | |
| Deletes all but the invisible Symantec files from the boot | |
| volume. Crontab entries are removed from the boot volume. | |
| $FullScriptName -C | |
| Deletes all Symantec files from the boot volume. No crontab | |
| entries are removed. | |
| $FullScriptName -L -A | |
| Lists all the files that $FullScriptName looks | |
| for on all volumes. The files may or may not be currently | |
| installed. Nothing is deleted. | |
| $FullScriptName -R -A | |
| Lists only the Symantec files that are currently installed | |
| on all volumes. Files within existing folders will also be | |
| shown. Nothing is deleted. | |
| $FullScriptName -l -i | |
| Lists the invisible Symantec files that are currently | |
| installed on the boot volume. Nothing is deleted. | |
| $FullScriptName -S | |
| Remove files only for product SEP | |
| Note: You must be root or an admin user to run this script. You can | |
| simply double-click on $FullScriptName to remove all | |
| Symantec files and crontab entries from the boot volume. | |
| " >>"$TEMPFILE" | |
| ShowContents "$TEMPFILE" | |
| /bin/rm "$TEMPFILE" 2>/dev/null | |
| [ "$1" ] && exit $1 | |
| } | |
| 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" | |
| } | |
| ShowVersion() | |
| { | |
| # Usage: ShowVersion | |
| # Summary: Displays the name and version of script. | |
| # | |
| echo "********* $FullScriptName $Version *********" | |
| } | |
| SymantecIsInMemory() | |
| { | |
| # Usage: SymantecIsInMemory | |
| # Summary: If a Symantec process or kext is in memory, | |
| # 0 is returned; 1 is returned. | |
| # | |
| local SymantecIsInMemoryResult=1 | |
| # If there are no more Symantec processes in memory | |
| if KillSymantecProcesses -n ; then | |
| : # 7.0.49: Commented out the following to avoid potential hang of kextstat (Etrack 3925328) | |
| # # Check to see if Symantec kexts are in memory | |
| # kextstat 2>/dev/null 1>&2 | |
| # # If kextstat failed to run | |
| # if [ $? -gt 0 ] ; then | |
| # # try running kmodstat (for old versions of OS X) | |
| # if [ "`kmodstat | grep -i Symantec | grep -v " grep -"` 2>/dev/null" ] ; then | |
| # SymantecIsInMemoryResult=0 | |
| # fi | |
| # elif [ "`kextstat | grep -i Symantec | grep -v " grep -"`" ] ; then | |
| # SymantecIsInMemoryResult=0 | |
| # fi | |
| # if [ $SymantecIsInMemoryResult = 0 ] ; then | |
| # echo "*** There are Symantec kexts loaded." | |
| # fi | |
| else | |
| SymantecIsInMemoryResult=0 | |
| fi | |
| return $SymantecIsInMemoryResult | |
| } | |
| YesEntered() | |
| { | |
| # Usage: YesEntered | |
| # Summary: Reads a line from standard input. If "y" or "yes" | |
| # was entered, true is shown and 0 is returned; otherwise, | |
| # false is shown and 1 is returned. The case of letters is | |
| # ignored. Sample call: | |
| # if `YesEntered` | |
| # | |
| read YesEnteredString | |
| YesEnteredString=`echo "z$YesEnteredString" | awk '{print tolower(substr($0,2))}'` | |
| if [ "'$YesEnteredString" = "'y" -o "'$YesEnteredString" = "'yes" ] ; then | |
| echo true | |
| return 0 | |
| fi | |
| echo false | |
| return 1 | |
| } | |
| function do_unload_sep_daemons() | |
| { | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.SymLUHelper.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.UninstallerToolHelper.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.deepsightdownload.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.dsp.nortonaggregatord.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.kexthelper.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.liveupdate.daemon.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.sharedsettings.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.symdaemon.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.symqual.detail.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.symqual.panicreporter.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.symqual.submit.MES.plist &>/dev/null | |
| launchctl bootout system /Library/LaunchDaemons/com.symantec.symseplps.MES.plis &>/dev/null | |
| launchctl unload /Library/LaunchAgents/com.symantec.uiagent.application.MES.plist &>/dev/null | |
| loggedInUser="" | |
| loggedInUser=$(/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }') | |
| if [ ! -z "$loggedInUser" ]; then | |
| su - "$loggedInUser" -c "launchctl unload /Library/LaunchAgents/com.symantec.uiagent.application.MES.plist" &>/dev/null | |
| fi | |
| } | |
| function do_load_daemons() | |
| { | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.SymLUHelper.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.UninstallerToolHelper.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.deepsightdownbootstrap system.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.dsp.nortonaggregatord.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.liveupdate.daemon.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.sharedsettings.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.symdaemon.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.symqual.detail.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.symqual.panicreporter.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.symqual.submit.MES.plist &>/dev/null | |
| launchctl bootstrap system /Library/LaunchDaemons/com.symantec.symseplps.MES.plist &>/dev/null | |
| loggedInUser="" | |
| loggedInUser=$(/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }') | |
| if [ ! -z "$loggedInUser" ]; then | |
| su - "$loggedInUser" -c "launchctl load /Library/LaunchAgents/com.symantec.uiagent.application.MES.plist" &>/dev/null | |
| fi | |
| } | |
| SEPApps=' | |
| /Applications/Symantec Endpoint Protection.app | |
| /Applications/Symantec Solutions/Symantec Endpoint Protection.app | |
| ' | |
| SEPReceiptsTable=' | |
| com.symantec.nortoninternetsecurity.sku.UniversalESD | |
| com.symantec.nortoninternetsecurity.Universal | |
| com.symantec.nortoninternetsecurity.sku.Universal | |
| ' | |
| SEPReceiptFolder="/Library/Application Support/Symantec/Uninstaller/Receipts" | |
| ReturnValueRemoveSEP=-1 | |
| RemoveSEP() | |
| { | |
| if [ "`whoami`" != "root" ] ; then | |
| printf "Remove production SEP only can be done in root, Script aborted." | |
| return -1 | |
| fi | |
| loggedInUser="" | |
| loggedInUser=$(/bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }') | |
| if [ -z "$loggedInUser" ]; then | |
| printf "need user login to run this scripts" | |
| return -1 | |
| fi | |
| # unload daemon to avoid uninstall dialog popup | |
| IsSilentUninstallableSingleAgent | |
| if [ $? -eq 0 ] ; then | |
| do_unload_sep_daemons | |
| fi | |
| local removedApplication=0 | |
| # os version great than 10.14 | |
| CompareMacOSVersion 10 14 | |
| if [ $? -eq 1 ] ; then | |
| IFS=$'\n' | |
| for sepApp in `echo "$SEPApps"` ; do | |
| if [ -d "$sepApp" ] ; then | |
| removedApplication=1 | |
| $ShowFilesAsRemoved && printf "remove applications ${sepApp}\n" | |
| if ! RemoveApp "$sepApp" ; then | |
| printf "remove ${sepApp} failed!\n" | |
| # reload daemons | |
| do_load_daemons | |
| return -1 | |
| fi | |
| fi | |
| done | |
| if [ $removedApplication -eq 0 ] ; then | |
| echo "cannot find application!" | |
| return -1 | |
| fi | |
| fi | |
| IsSilentUninstallableSingleAgent | |
| if [ $? -eq 1 ] ; then | |
| # single agent just exit, let applicatin remove rest of files | |
| echo "Please remove rest of files from uninstallation dialog" | |
| exit 0 | |
| fi | |
| CurrentDir="`pwd`" | |
| cd / | |
| # run predelete | |
| IFS=$'\n' | |
| for receipt in `echo "$SEPReceiptsTable"` ; do | |
| if [ -f "${SEPReceiptFolder}/${receipt}/predelete" ] ; then | |
| PredeleteScript="${SEPReceiptFolder}/${receipt}/predelete" | |
| if $ShowPredeleteErrors ; then | |
| PredeleteScriptProgram=`head -n 1 "$PredeleteScript" | grep '^#!'` | |
| PredeleteScriptProgram=`basename "$PredeleteScriptProgram"` | |
| # If predelete script is a bash or sh script | |
| if [ "z$PredeleteScriptProgram" = zbash -o "z$PredeleteScriptProgram" = zsh ] ; then | |
| # Pass -vx to script interpreter to show verbose output | |
| echo "$PredeleteScriptProgram -vx \"$PredeleteScript\"" | |
| "$PredeleteScriptProgram" -vx "$PredeleteScript" | |
| else | |
| echo "$PredeleteScript" | |
| "$PredeleteScript" | |
| fi | |
| else | |
| "$PredeleteScript" 2>/dev/null 1>&2 | |
| fi | |
| echo "Predelete script exited with $?" | |
| echo ">>>>>>>>>>>> Predelete run ENDED at: `date +"%Y-%m-%d %H:%M:%S"` <<<<<<<<<<<<" | |
| fi | |
| RemoveItem "${SEPReceiptFolder}/${receipt}" | |
| done | |
| # remove files | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.nis.uninstall.Universal.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.nis.uninstall.UniversalESD.plist" | |
| RemoveItem "/Library/Application Support/nis_UniversalESD_Data2.chk" | |
| RemoveItem "/Library/Application Support/nis_UniversalESD_postuninstall.rb" | |
| RemoveItem "/Library/Application Support/nis_UniversalESD_uninstalldashboard" | |
| RemoveItem "/Library/Application Support/Symantec/Silo" | |
| # sepeg | |
| RemoveItem "/Library/LaunchAgents/com.symantec.uiagent.application.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.SymLUHelper.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.UninstallerToolHelper.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.deepsightdownload.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.dsp.nortonaggregatord.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.kexthelper.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.liveupdate.daemon.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.sharedsettings.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.symdaemon.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.symqual.detail.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.symqual.panicreporter.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.symqual.submit.MES.plist" | |
| RemoveItem "/Library/LaunchDaemons/com.symantec.symseplps.MES.plist" | |
| RemoveItem "/usr/local/lib/libecomlodr.dylib" | |
| RemoveItem "/private/etc/symantec/defutils.conf" | |
| RemoveItem "/Applications/Symantec Solutions/SyLinkDrop.app" | |
| RemoveItem "/Applications/Symantec Endpoint Protection.app" | |
| RemoveItem "/Applications/Symantec Solutions/Symantec Endpoint Protection.app" | |
| RemoveItem "/Library/Application Support/Symantec/Registry" | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Tools/symuninstallutility" | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Receipts/SEFDefs.zip" | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Receipts/addRights" | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Receipts/applefirewall" | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Receipts/navdefutil" | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Receipts/networkList" | |
| RemoveItem "/Library/Application Support/Symantec/DebugSiloPath" | |
| RemoveItem "/Library/Services/Symantec.service" | |
| RemoveItem "/Library/Services/NortonDocktile.bundle" | |
| RemoveItem "/Library/Services/Symantec for Mac.service" | |
| # invalid cache | |
| RemoveItem "/Library/Extensions/NortonForMac.kext" | |
| RemoveItem "/Library/Extensions/SymIPS.kext" | |
| RemoveItem "/Library/Extensions/SymXIPS.kext" | |
| RemoveItem "/Library/Extensions/SymInternetSecurity.kext" | |
| RemoveItem "/Applications/Symantec Solutions" -e | |
| RemoveItem "/private/etc/symantec" -e | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Receipts" -e | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller/Tools" -e | |
| RemoveItem "/Library/Application Support/Symantec/Uninstaller" -e | |
| RemoveItem "/Library/Application Support/Symantec/Daemon" -e | |
| RemoveItem "/Library/Application Support/Symantec" -e | |
| # recover current folder | |
| cd "$CurrentDir" | |
| kextcache -invalidate / | |
| ReturnValueRemoveSEP=0 | |
| return 0 | |
| } | |
| # *** Beginning of Commands to Execute *** | |
| # Verify that all required programs are installed - Etrack 3539262 | |
| which which &>/dev/null | |
| if [ $? = 0 ] ; then | |
| MissingRequiredPrograms="" | |
| SavedIFS="$IFS" | |
| IFS=' | |
| ' | |
| for RequiredProgram in $RequiredPrograms ; do | |
| which "$RequiredProgram" &>/dev/null | |
| [ $? != 0 ] && MissingRequiredPrograms="$MissingRequiredPrograms | |
| $RequiredProgram" | |
| done | |
| IFS="$SavedIFS" | |
| else | |
| MissingRequiredPrograms=" | |
| which" | |
| fi | |
| if [ "$MissingRequiredPrograms" ] ; then | |
| echo | |
| echo "WARNING: Could not continue because the following program(s) could not be found:" | |
| echo "$MissingRequiredPrograms" | |
| echo | |
| exit 2 | |
| fi | |
| ScriptPath=`ShowFullFilePath "$0" -P` | |
| ScriptDir=`dirname "$ScriptPath"` | |
| 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 | |
| # If script was run from support folder or from within an app bundle | |
| if [ "`echo "$ScriptDir" | grep -e "$LaunchLocationGrepPattern"`" ] ; then | |
| RunScriptAsStandAlone=false | |
| RunningFromWithinAppBundleOrSupportFolder=true | |
| else | |
| RunningFromWithinAppBundleOrSupportFolder=false | |
| fi | |
| if $RunScriptAsStandAlone ; then | |
| clear >&2 | |
| fi | |
| ProcessArguments --OptionIsOneArgument="-QQ" --OptionIsOneArgument="-re" "$@" | |
| OSXVersion=`defaults read /System/Library/CoreServices/SystemVersion.plist ProductVersion` | |
| OSXmajorVersion=`printf "%s" "$OSXVersion" | awk -F . '{print $2}'` | |
| if $OnlyRemoveSEP ; then | |
| printf "will remove product SEP \n" | |
| RemoveSEP | |
| if [ $? -eq 0 ] ; then | |
| RestartComputer | |
| fi | |
| exit $ReturnValueRemoveSEP | |
| fi | |
| ProcessDummyAppRemoval | |
| ProcessAppRemoval | |
| IsSilentUninstallableSingleAgent | |
| if [ $? -eq 1 ] ; then | |
| # single agent just exit, let applicatin remove rest of files | |
| echo "Please remove rest of files from uninstallation dialog" | |
| ExitScript 0 | |
| fi | |
| if [ -d /Users/corey_swertfager -a -L /Volumes/SOE -a $CreateFilesRemovedListOnly = false ] ; then | |
| ExitScript 0 | |
| fi | |
| if [ "`whoami`" != "root" ] ; then # If not root user, | |
| if $PublicVersion ; then | |
| GetAdminPassword true # Prompt user for admin password | |
| elif ! $DoShowOnlyFilesThatShouldHaveBeenUninstalled ; then | |
| ShowVersion >&2 | |
| echo >&2 | |
| 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." >&2 | |
| ExitScript 1 | |
| fi | |
| if $PublicVersion ; then | |
| sudo -k # Make sudo require a password the next time it is run | |
| fi | |
| exit $ErrorFromSudoCommand # Exit so script doesn't run again | |
| fi | |
| # If no volumes were passed to script, the boot volume will be searched | |
| if [ -z "$VolumesToUse" ] ; then | |
| BootVolumeWillBeSearched=true | |
| fi | |
| if [ $PublicVersion = true -a $CreateFilesRemovedListOnly = false -a \ | |
| $RemoveCrontabEntriesOnly = false -a $RemoveInvisibleFilesOnly = false -a \ | |
| $AutoRunScript = false -a $RunningFromWithinAppBundleOrSupportFolder = false ] ; then | |
| DetermineAction | |
| fi | |
| if [ $RemoveFromAllVolumes = true -a $CreateFilesRemovedListOnly = false -a $RemoveCrontabEntriesOnly = false -a $RemoveInvisibleFilesOnly = false -a $AutoRunScript = false -a $RunningFromWithinAppBundleOrSupportFolder = false ] ; then | |
| echo | |
| printf "Are you sure you want to remove Symantec files from ALL mounted volumes (y/n)? " | |
| if `YesEntered` ; then | |
| echo | |
| else | |
| echo | |
| echo "Script aborted. No files were removed." | |
| ExitScript 0 | |
| fi | |
| fi | |
| SetupCleanup | |
| WillTense=will | |
| if $CreateFilesRemovedListOnly ; then | |
| if ! $DoShowOnlyFilesThatShouldHaveBeenUninstalled ; then | |
| echo "Generating a list of files that would be removed by" >&2 | |
| echo " $FullScriptName (no files will be removed at this time)..." >&2 | |
| fi | |
| WillTense=would | |
| elif $RemoveInvisibleFilesOnly ; then | |
| echo "Removing AntiVirus QuickScan files and Symantec FS files..." | |
| else | |
| if $BootVolumeWillBeSearched ; then | |
| if [ $RestartAutomatically = true -a $RemoveCrontabEntriesOnly = false ] ; then | |
| echo | |
| echo "Note: Computer will be restarted automatically if necessary." | |
| echo | |
| elif $QuitWithoutRestarting ; then | |
| echo | |
| echo "Note: This script will automatically quit when finished." | |
| echo | |
| fi | |
| fi | |
| echo "Removing Symantec files..." | |
| ! $RemoveInvisibleFiles && echo "Invisible Symantec files will not be deleted." | |
| fi | |
| if $RemoveCrontabEntriesOnly ; then | |
| echo "Only crontab entries $WillTense be removed." | |
| fi | |
| ! $RemoveCrontabEntries && echo "Symantec crontab entries $WillTense not be removed." | |
| ! $RemoveInvisibleFiles && echo "AntiVirus QuickScan and Symantec FS files $WillTense not be removed." | |
| if $RemoveFromAllVolumes ; then | |
| VolumesToUse="/ | |
| "`ls -d /Volumes/*` | |
| elif ! $RemoveFromOtherVolumes ; then | |
| VolumesToUse=/ | |
| fi | |
| ListOfVolumesToUse=`echo "$VolumesToUse" | sort -f | uniq` | |
| IFS=' | |
| ' | |
| for EachVolume in $ListOfVolumesToUse ; do | |
| [ -L "$EachVolume" ] && continue | |
| FilesFoundOnThisVolume=false | |
| RemoveAllSymantecFiles "$EachVolume" | |
| if [ $CreateFilesRemovedListOnly = true -a $FilesFoundOnThisVolume = false -a $ListOnlyFilesThatExist = true ] ; then | |
| echo "No matching files were found on \"`basename "$EachVolume"`\"." >> "$FilesRemovedList" | |
| fi | |
| done | |
| FinishCleanup | |
| FinishedExitCode=$? | |
| if [ $BootVolumeWillBeSearched = true -a $CreateFilesRemovedListOnly = false ] ; then | |
| # If some Symantec process or kext is in memory, touch restart file | |
| if SymantecIsInMemory ; then | |
| # touch of Extensions folders may not be necessary, since restart is triggered (Etrack 3925328) | |
| touch "$SymantecCleanupRestartFile" # /Library/Extensions /System/Library/Extensions | |
| # May run kextcache in a future release: | |
| # echo "Rebuilding kext caches" | |
| # kextcache -u / | |
| fi | |
| if [ -f "$SymantecCleanupRestartFile" ] ; then | |
| echo | |
| echo "NOTE: You should now restart the computer to get Symantec processes" | |
| echo " and kexts out of memory and/or to remove login items." | |
| RestartComputer | |
| elif [ -e /Library/StartupItems/CleanUpSymWebKitUtils ] ; then | |
| echo | |
| echo "NOTE: You should now restart the computer to have CleanUpSymWebKitUtils" | |
| echo " finish removing SymWebKitUtils.framework." | |
| RestartComputer | |
| fi | |
| fi | |
| ExitScript $FinishedExitCode | |
| # *** End of Commands to Execute *** |