Repair procedure script with problems

Well, I finally thought I had this script finished but I’ve discovered a few problems.

First of all, I guess I’ll describe what I’d like to have, and then what I’m actually getting.

The first part is basically to weed out any situations where the script doesn’t actually need to be run, this part works okay as far as I know. The part that actually runs the repair procedure upon the “else if ((disk_utilitys_permissions_ is not equal to “-rwsrwxr-x 1 root admin”) and (sudos_permissions_ is equal to “-r-s–x–x 1 root wheel”)) then” is where I’m beginning to have problems.

Number one, I don’t have a strong grasp of subroutines and tend to avoid them as much as possible ;-). If Disk Utility is running, I would basically like to give the user a choice to automatically quit DU and continue, or to hit Cancel to quit out of my script. Right now, selecting “automatically quit DU and continue” works okay, but I’m having trouble with the Cancel button working to quit out of the sript. I hit cancel, and it still proceeds to the repair procedure without even quitting DU.

Then for the repair procedure–this thing is driving me nuts… I would basically like to do the "do shell script “sh -c " & quoted form of sh_chown_chmod_ with administrator privileges” and then if it fails for whatever reason, I give the user a choice of “Trying Again” or the opportunity to quit out of the script (“Quit”). The way I have it set up right now, um, sort of works, in that say I do the following::

  1. At the prompt for my password, I accidentally type the wrong one.
  2. I get an error message and a choice. I choose to Try Again.
  3. At the prompt for my password, I accidentally press enter before entering my password.
  4. Since I do have a password (it’s not blank), I get an error message and a choice again. I choose Try Again.
  5. This time I enter my password correctly and the script executes the “do shell script” successfully.

The only problem here is that I get like 3 or 4 displayed alerts that say “Disk Utility’s Permissions were repaired.” Obviously I only need one but I’m kind of lost at this point on how to achieve that.

Any help would be greatly appreciated.

Thanks in advance…

PS, as you may have noticed, this script is intended only for Jaguar, but I temporarily edited the setup to allow me to run it in Panther so that I get to the “repair is necessary and possible” stage. (Permissions on Disk Utility and /usr/bin/sudo differ between Jaguar and Panther). Anyway, here’s the script:

using terms from application "Xcode"
    
    -- target permission settings:

    -- Disk Utility:
    -- "-rwsrwxr-x  1 root  admin"
    
    -- sudo:
    -- "---s--x--x  1 root  wheel"
    
    -- test.applescript
    -- test
    
    --  Created by Mark Douma on Sun Jan 11 2004.
    --  Copyright (c) 2004 Mark Douma. All rights reserved.
    property success_ : false
    
    on launched theObject
        copy my gestaltVersion_info("sysv", 4) to {system_version, system_string}
        if the system_version is less than "1020" then
            display alert "Repair Disk Utility's Permissions only works with Mac OS X 10.2.0 - 10.2.8!" message "The currently installed version of OS X is: " & system_string default button "Quit"
            quit me
        else if the system_version is greater than "1033" then
            display alert "Repair Disk Utility's Permissions only works with Mac OS X 10.2.0 - 10.2.8!" message "The currently installed version of OS X is " & system_string default button "Quit"
            quit me
        end if
        
        -- get Disk Utility's current permissions
        set disk_utilitys_long_permissions_ to do shell script "ls -l /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility"
        set disk_utilitys_permissions_ to text 1 thru 25 of disk_utilitys_long_permissions_
        
        -- get "sudo's" current permissions. If they're damaged, there's no way to repair permissions but to boot from an OS X CD and run DU from there.
        set sudos_long_permissions_ to do shell script "ls -l /usr/bin/sudo"
        set sudos_permissions_ to text 1 thru 25 of sudos_long_permissions_
        
        -- begin evaluation of Disk Utility's and sudo's permissions
        if disk_utilitys_permissions_ is equal to "-rwsrwxr-x  1 root  admin" then
            display alert "Disk Utility's permissions are fine." message "There's no need to run this application." default button "Quit"
            quit me
        else if ((disk_utilitys_permissions_ is not equal to "-rwsrwxr-x  1 root  admin") and (sudos_permissions_ is not equal to "-r-s--x--x  1 root  wheel")) then
            display alert "Disk Utility's permissions are damaged and need to be repaired. Unfortunately, the permissions of your OS X installation are too severely damaged for "Repair Disk Utility's Permissions" to repair them." message "You need to start up from your OS X 10.2 install CD and run Disk Utility's "Repair Permissions" feature off of the CD. To do this, Insert your Mac OS X CD-ROM disc or Restore DVD disc, then restart the computer while holding the C key. Once started up from CD or DVD, choose Disk Utility from the Installer menu." default button "Quit"
            quit me
        else if ((disk_utilitys_permissions_ is not equal to "-rwsrwxr-x  1 root  admin") and (sudos_permissions_ is equal to "-r-s--x--x  1 root  wheel")) then
            display alert "Disk Utility's permissions are damaged and need to be repaired." message "Press "Repair" to repair Disk Utility's permissions." default button "Repair" other button "Cancel"
            if button returned of result = "Repair" then
                make_sure_DU_aint_running_()
                execute_repair_()
            else
                quit me
            end if
        end if
        quit me
    end launched
    
    on make_sure_DU_aint_running_()
        tell application "System Events"
            set running_applications_ to get name of every application process
        end tell
        if running_applications_ contains "Disk Utility" then
            display alert "Disk Utility should not be running while we repair its permissions." message "Press "Quit Disk Utility & Continue" to automatically quit Disk Utility and then proceed with the repair process." default button "Quit Disk Utility & Continue" other button "Cancel"
            if button returned of result = "Quit Disk Utility & Continue" then
                tell application "Disk Utility"
                    quit
                end tell
            else if the button returned of result = "Cancel" then
                quit me
            end if
        end if
    end make_sure_DU_aint_running_
    
    on execute_repair_()
        set sh_chown_chmod_ to "sudo chown 0 /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility; sudo chmod 4775 /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility"
        try
            do shell script "sh -c " & quoted form of sh_chown_chmod_ with administrator privileges
        on error error_message_ number error_number_
            if error_message_ contains ("Sorry, try again" as Unicode text) then
                display alert "The password you entered is incorrect" default button "Try Again" other button "Quit"
                if the button returned of result = "Quit" then
                    quit me
                else if button returned of result = "Try Again" then
                    execute_repair_()
                end if
            else if error_number_ is -927 then
                try
                    set arbitrary_password_ to "blank"
                    do shell script {"sh -c " & quoted form of sh_chown_chmod_} password arbitrary_password_ with administrator privileges
                    return arbitrary_password_
                on error error_message_
                    display alert "The password you entered is incorrect" default button "Try Again" other button "Quit"
                    if the button returned of result = "Quit" then
                        quit me
                    else if button returned of result = "Try Again" then
                        execute_repair_()
                    end if
                end try
            else
                execute_repair_()
            end if
        end try
        set disk_utilitys_long_permissions_ to do shell script "ls -l /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility"
        set disk_utilitys_permissions_ to text 1 thru 25 of disk_utilitys_long_permissions_
        if disk_utilitys_permissions_ is equal to "-rwsrwxr-x  1 root  admin" then
            set success_ to true
            display alert "Disk Utility's permissions were repaired." message "You can now return to Disk Utility and repair the permissions on the rest of your disk." default button "OK"
        end if
        if success_ = true then
            tell application "Finder"
                open file ":Applications:Utilities:Disk Utility.app:"
            end tell
        end if
    end execute_repair_
    
    
    on gestaltVersion_info(gestalt_code, string_length)
        try
            tell application "Finder" to copy my NumToHex((system attribute gestalt_code), string_length) to {a, b, c, d}
            set the numeric_version to {a, b, c, d} as string
            if a is "0" then set a to ""
            set the version_string to (a & b & "." & c & "." & d) as string
            return {numeric_version, version_string}
        on error
            return {"", "unknown"}
        end try
    end gestaltVersion_info
    
    on NumToHex(hexData, stringLength)
        set hexString to {}
        repeat with i from stringLength to 1 by -1
            set hexString to ((hexData mod 16) as string) & hexString
            set hexData to hexData div 16
        end repeat
        return (hexString as string)
    end NumToHex
    
end using terms from

Just thought I’d post back with my solution FWIW. Any comments on it would be welcome.


-- Disk Utility:
-- "-rwsrwxr-x  1 root  admin"

-- sudo:
-- "---s--x--x  1 root  wheel"

-- Repair Disk Utility's Permissions.applescript
-- Repair Disk Utility's Permissions

--  Created by Mark Douma on Sat Jan 17 2004.
--  Copyright (c) 2004 Mark Douma. All rights reserved.

on launched theObject
    copy my gestaltVersion_info("sysv", 4) to {system_version, system_string}
    if the system_version is less than "1020" then
        display alert "Repair Disk Utility's Permissions only works with Mac OS X 10.2.0 - 10.2.8!" as critical message "The currently installed version of OS X is: " & system_string default button "Quit"
        if button returned of result = "Quit" then
            quit me
            return
        end if
    else if the system_version is greater than "1028" then
        display alert "Repair Disk Utility's Permissions only works with Mac OS X 10.2.0 - 10.2.8!" as critical message "The currently installed version of OS X is " & system_string default button "Quit"
        if button returned of result = "Quit" then
            quit me
            return
        end if
    end if
    
    -- get Disk Utility's current permissions
    set disk_utilitys_long_permissions_ to do shell script "ls -l /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility"
    set disk_utilitys_permissions_ to text 1 thru 25 of disk_utilitys_long_permissions_
    
    -- get "sudo's" current permissions. If they're damaged, there's no way to repair permissions but to boot from an OS X CD and run DU from there.
    set sudos_long_permissions_ to do shell script "ls -l /usr/bin/sudo"
    set sudos_permissions_ to text 1 thru 25 of sudos_long_permissions_
    
    -- begin evaluation of Disk Utility's and sudo's permissions
    if disk_utilitys_permissions_ is equal to "-rwsrwxr-x  1 root  admin" then
        display alert "Disk Utility's permissions are fine." message "There's no need to run this application." default button "Quit"
        quit me
    else if ((disk_utilitys_permissions_ is not equal to "-rwsrwxr-x  1 root  admin") and (sudos_permissions_ is not equal to "---s--x--x  1 root  wheel")) then
        display alert "Disk Utility's permissions are damaged and need to be repaired. Unfortunately, the permissions of your OS X installation are too severely damaged for "Repair Disk Utility's Permissions" to repair them." as critical message "You need to start up from your OS X 10.2 install CD or Restore CD/DVD disc and run Disk Utility's "Repair Permissions" feature from that. To do this, insert your Mac OS X CD or Restore CD/DVD disc, then restart the computer while holding the C key. Once started up from CD/DVD, choose Disk Utility from the Installer menu." default button "Quit"
        quit me
    else if ((disk_utilitys_permissions_ is not equal to "-rwsrwxr-x  1 root  admin") and (sudos_permissions_ is equal to "---s--x--x  1 root  wheel")) then
        display alert "Disk Utility's permissions are damaged and need to be repaired." as critical message "Press "Repair" to repair Disk Utility's permissions." default button "Repair" other button "Cancel"
        if button returned of result = "Repair" then
            set proceed_ to make_sure_DU_aint_running_()
            if proceed_ = true then
                set what_to_do_ to 0
                repeat until execute_repair_(what_to_do_) is greater than or equal to 1
                end repeat
                if what_to_do_ = 1 then
                    quit me
                else if what_to_do_ = 2 then
                    return
                end if
            else
                quit me
            end if
        else
            quit me
        end if
    end if
    quit me
end launched

on execute_repair_(what_to_do_)
    set sh_chown_chmod_ to "sudo chown 0 /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility; sudo chmod 4775 /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility"
    try
        do shell script "sh -c " & quoted form of sh_chown_chmod_ with administrator privileges
    on error error_message_ number error_number_
        if error_message_ contains ("Sorry, try again" as Unicode text) then
            display alert "The password you entered is incorrect." as critical message "Would you like to try again?" default button "Try Again" other button "Quit"
            if the button returned of result = "Quit" then
                set what_to_do_ to 1
                return what_to_do_
            else if button returned of result = "Try Again" then
                set what_to_do_ to 0
                return what_to_do_
            end if
        else if error_number_ is -927 then
            try
                set arbitrary_password_ to "blank"
                do shell script ("sh -c " & quoted form of sh_chown_chmod_) password arbitrary_password_ with administrator privileges
            on error error_message_
                display alert "The password you entered is incorrect." as critical message "Would you like to try again?" default button "Try Again" other button "Quit"
                if the button returned of result = "Quit" then
                    set what_to_do_ to 1
                    return what_to_do_
                else if button returned of result = "Try Again" then
                    set what_to_do_ to 0
                    return what_to_do_
                end if
            end try
        else
            display alert "Error!" as critical message error_message_ & return & return & error_number_ & return & return & "Would you like to try again?" default button "Try Again" other button "Quit"
            if the button returned of result = "Quit" then
                set what_to_do_ to 1
                return what_to_do_
            else if button returned of result = "Try Again" then
                set what_to_do_ to 0
                return what_to_do_
            end if
        end if
    end try
    set disk_utilitys_long_permissions_ to do shell script "ls -l /Applications/Utilities/Disk\ Utility.app/Contents/MacOS/Disk\ Utility"
    set disk_utilitys_permissions_ to text 1 thru 25 of disk_utilitys_long_permissions_
    if disk_utilitys_permissions_ is equal to "-rwsrwxr-x  1 root  admin" then
        display alert "Disk Utility's permissions were repaired." message "You can now return to Disk Utility and repair the permissions on the rest of your disk." default button "OK"
    end if
    tell application "Finder"
        open file ":Applications:Utilities:Disk Utility.app:"
    end tell
    set what_to_do_ to 2
    return what_to_do_
end execute_repair_

on make_sure_DU_aint_running_()
    tell application "System Events"
        set running_applications_ to get name of every application process
    end tell
    if running_applications_ contains "Disk Utility" then
        display alert "Disk Utility should not be running while we repair its permissions." as critical message "Press "Quit Disk Utility & Continue" to automatically quit Disk Utility and then proceed with the repair process." default button "Quit Disk Utility & Continue" other button "Cancel"
        if button returned of result = "Quit Disk Utility & Continue" then
            tell application "Disk Utility"
                delay 1 -- to prevent "Disk Utility got an error: Connection is invalid. (-609)"
                quit
            end tell
            return true
        else if the button returned of result = "Cancel" then
            return false
        end if
    else
        return true
    end if
end make_sure_DU_aint_running_

on gestaltVersion_info(gestalt_code, string_length)
    try
        tell application "Finder" to copy my NumToHex((system attribute gestalt_code), string_length) to {a, b, c, d}
        set the numeric_version to {a, b, c, d} as string
        if a is "0" then set a to ""
        set the version_string to (a & b & "." & c & "." & d) as string
        return {numeric_version, version_string}
    on error
        return {"", "unknown"}
    end try
end gestaltVersion_info

on NumToHex(hexData, stringLength)
    set hexString to {}
    repeat with i from stringLength to 1 by -1
        set hexString to ((hexData mod 16) as string) & hexString
        set hexData to hexData div 16
    end repeat
    return (hexString as string)
end NumToHex