How old will you be when you realize you’re dead?

Posted October 2, 2009 by bigmaconcampus
Categories: Rhinoism

Tags:

While having a discussion with Rhino about the fact that I didn’t realize how many years had passed after the death of my Father, she offered this nugget of wisdom.

“Yeah, time really flies by. I was almost seven before I knew I’d been born.”

Baking: Where you get to eat your mistakes

Posted September 24, 2009 by bigmaconcampus
Categories: Misc

Tags: , , ,

Expanding from Mac-Tech and Rhinoisms to cake-making in this post.

Over the years, I’ve made several different birthday cakes for the kids that required extra commitment to finish. I haven’t done this for every birthday, it’s more of a treat. Anyway, thought I’d share some photos of a few of them in case anyone is looking for some ideas. The wife is currently already putting in a request for a “Twilight Cake” for her next birthday. If this happens, I’ll probably post it also.

Photo Booth is a freaky little application

Posted September 3, 2009 by bigmaconcampus
Categories: Mac Tech

Tags: , , ,

While working on a simple web-cam setup for one of our areas as a temporary measure until the real setup gets put in place, I ran into several odd issues.

The strangest being Photo Booth. We won’t even go into the long road of details on how I wound up using Photo Booth or the fact that I had issues with isightcapture on a Mac Mini running Tiger and had to resort to a sad little, hacked together AppleScript.

My discovery (thanks to a co-worker, since I’d have never thought of this) was that Photo Booth forces you to either have a monitor or a video adapter connected to a PowerPC Mac Mini or else the application refuses to take pictures.

Seriously.

The only, and I mean only, thing that I can possibly rationalize is that Photo Booth makes the screen flash white (like a flash bulb) and must have some requirement for a screen to be attached.

Really Apple, what in Hades name could you have possibly been thinking? This ought to be an interesting bug report when they get it.

Brother Love

Posted September 3, 2009 by bigmaconcampus
Categories: Rhinoism

Tags: ,

While observing her brothers hug after beating a video game…

Rhino: “Brother love…. I’ll never know it.”

Wireless Installer – The Next Generation

Posted August 27, 2009 by bigmaconcampus
Categories: Mac Tech

Tags: , , , , , , , , , , , , , , , , , , , , ,

Ok, after originally posting the code for my wireless installer, I’ve updated the code earlier in the summer and keep promising to post an update. Without further adieu, here it finally is.

*NOTE* 9/29/09
There were some errors in the applescript sections of the original post. These should be correct now. Oops.

Since I couldn’t remember specifically what I changed (several bug fixes, some major, some minor), I’ll re-post the entire thing here. It has been tested on over 1700 Macs since the beginning of June 2009, so I consider it fairly solid at this point.

There was an entire section redone in C code since there were certain APIs that could only be addressed that way. This was also the ONLY piece that was a reminant of a GUI based version I’d made a year beforehand. Now, all command line, YEAH. (Thanks Kim!) Also, now moves the newly added wireless network to the top of the preferred list so connection time is quicker (noticed that with users that had 20+ wireless networks, adding it to the end of the list resulted in several minute long connection times).

The only issues I’ve run into is that on occasional runs, the installer will not pickup the wireless username correctly (the main script thinks that the wireless username is blank). I haven’t been able to narrow down what causes it directly (I think it has to do with running the installer partially and quitting at a certain spot, which must be leaving some clutter behind, but haven’t directly proved this yet), but have added code to recognize the problem and exit with an error. Most times, running the installer a second time will work fine. (If anyone happens to figure it out, please let me know in the comments)

The other small issue shows about one in a hundred runs and I consider it an applescript bug. Sometimes the portion that is applescript won’t allow the user to type in the dialog box. A reboot solves this behavior.

This installer basically works the same as before, it is crammed into a PackageMaker .pkg file and runs as a postscript to perfom the setup. The beauty of this is that it can be posted on a website for the user’s to run themselves and doesn’t require a tech to setup their wireless for them. (Makes our lines MUCH shorter). If you are confused by any of the details, refer to the previous post for a deeper description of some portions.

It’s in several scripts in several different languages (Four in all I think, we almost had some perl in it, but I’m a Bash junkie and got it to work in less lines in Bash :P )

Change Log

July 2009
Version 3.6
Fixed bug that caused a blank wireless username in certain situations
Fixed bug with a ’space’ in the Mac password
Wireless network is now added in the top location of preferred networks to enable faster connection
Added more error codes
Added better error descriptions
Added ‘retry counter’ to dialogs
Lowered number of retries from five to three

April 2009
Version 3.5
Rebuilt Keychain creation mechanism in C to solve several bugs centering around creation of ACL of Keychain and Assistive Devices settings.
Added Mac OS X 10.6 enhancements
Increased speed of installer
Added second wireless password test in case of system outage

March 2009
Version 3.1
Made compatible with Mac OS X 10.6 (Snow Leopard)
Added several exceptions for MacBook Air hardware types due to lack of ethernet port
Streamlined method of fixing certain symbol characters in passwords
Fixed bug with toggling Assistive Devices settings
Modified handling of certain preference files and previous Enterprise level network setups
Added steps to handle a blank Mac Password
Added error code for a corrupt login.keychain that cannot be unlocked

Main Bash Script (wireless_setup.sh runs as postscript in the .pkg installer)
#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

#################################################
# Wireless Setup Script #
# Created by Bryan S. Lee 2009 #
#################################################

###################################################
### VARIABLES THAT MUST BE SET BEFORE RUNNING!!!!!#
###################################################

### Temp folder location for installation files
TEMP="/private/tmp/foo"

### Location of PlistBuddy
PLISTBUDDY="$TEMP/PlistBuddy"

### New Wireless Network to be setup and legacy networks to remove
WIRELESSNETWORKNAME="nameofwirelessnetwork"
LEGACYNETWORK1="nameofoldwirelessnetwork"
LEGACYNETWORK2="nameofoldopenwirelessnetwork"

##########################################################
### Initial state variables that probably don't change ###
##########################################################

### Variable that tests whether a previous setup is detected later in the script
PREV_WIRELESS_EXISTS=""

### Variable that tests if a legacy network is present. To be used later in the script
PREV_LEGACY1_EXISTS=""

### Variable that tests if a second legacy network is present. To be used later in the script
PREV_LEGACY2_EXISTS=""

### Set other variables
LOCALUSER=`whoami`
HOME=`dscl . -read /Users/$LOCALUSER home | sed -e 's|dsAttrTypeNative:home: ||g'`
LOG=$HOME/Library/Logs/foo_Setup.log
REPORTER="$TEMP/wireless-install-report.sh"
SYSTEMPROFILE="$TEMP/system_profile.txt"
system_profiler -detailLevel mini > $SYSTEMPROFILE
OSVERSION=`grep "System Version:" $SYSTEMPROFILE | cut -c 32-35`

### Setup Error log for later use in case of errors. Duh!
ERRORLOG="$TEMP/error.log"
ERROR=""
rm -rf $TEMP/error.log
touch $TEMP/error.log

# Check hardware to see if computer is a MacBookAir, if so, change Wireless Interface variable to en0
# instead of en1 to accomodate hardware difference (no ethernet at en0 on MacBookAir, airport is en0 instead)
# Also, set variable MBAirPresent to pass to get_wireless_pass.scpt, to bypass network test if applicable.
WIRELESSINTERFACE="en1"
CHECKFORAIR=`grep MacBookAir $SYSTEMPROFILE`
if [ "$CHECKFORAIR" != "" ]; then
echo "MacBookAir detected, changing Wireless Interface to en0..." >> $LOG
WIRELESSINTERFACE="en0"
MBAirPresent="true"
else
MBAirPresent="false"
fi

#####################
### FUNCTIONS ###
#####################

# Function for checking error log file for any possible errors coming from Applescript portions
CHECK_FOR_ERRORS ()
{
ERROR=`grep exit $ERRORLOG | cut -c 1-7`
if [ "$ERROR" != "" ]; then
$REPORTER
rm -rf /tmp/foo
$ERROR
fi
}

# Fuction that will report back the position counts in plist files to the Log
PLISTCOUNTER ()
{
((PLISTITEMCOUNT=$PLISTITEMCOUNT+1))
echo "Entries start at 0, and current number of entries is " $PLISTITEMCOUNT >> $LOG
echo "Next entry number position will be " $PLISTITEMCOUNT >> $LOG
}

# Function that toggles the airport between on and off. Expects on or off as variables of the function
TOGGLEAIRPORT ()
{
echo "Turning $1 Airport wireless..." >> $LOG
if [ "$OSVERSION" = "10.5" ]; then
networksetup -setairportpower $1
else
if [ "$OSVERSION" = "10.6" ]; then
networksetup -setairportpower $WIRELESSINTERFACE $1
else
osascript -e "tell application \"Finder\" to activate"
osascript -e "tell application \"Finder\" to display dialog \"An error occurred while attempting to turn the wireless on or off. Please try the installer again or contact the Computer Support Center for help.\" buttons {\"OK\"} with icon caution"
osascript -e "tell application \"Installer\" to activate"
echo "exit 20 Error occurred while changing airport power due to unknown operating system version." >> $LOG
echo "exit 20 Error occurred while changing airport power due to unknown operating system version." > $ERRORLOG
fi
fi
echo "Airport wireless turned $1" >> $LOG
}

######################
### Starting Setup ###
######################

# Setup the log so we know what's going on later...
echo "------------------------------------------------------------------" >> $LOG
echo "Wireless Setup started at `date`" >> $LOG
echo "Starting Wireless Setup..." >> $LOG
echo "------------------------------------------------------------------" >> $LOG
echo "" >> $LOG

grep "System Version:" $SYSTEMPROFILE | cut -c 7-50 >> $LOG

# Turn on Airport to test if Wireless network to join is present
TOGGLEAIRPORT on

CHECK_FOR_ERRORS

### Check to see if Wireless Network is within range (only works with broadcast SSID)
echo "Checking to see if wireless network, $WIRELESSNETWORKNAME, is within range for setup to continue..." >> $LOG
WIRELESSINRANGE=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport --scan=$WIRELESSNETWORKNAME`
if [ "$WIRELESSINRANGE" = "No networks found" ]; then
echo "$WIRELESSNETWORKNAME not within range, installation will quit" >> $LOG
osascript -e "tell application \"Finder\" to activate"
osascript -e "tell application \"Finder\" to display dialog \"The wireless network, $WIRELESSNETWORKNAME, is not within range.\" & return & return & \"The installer will now quit. Please move to within range of the wireless signal and try again.\" buttons {\"OK\"} with icon caution"
osascript -e "tell application \"Installer\" to activate"
echo "exit 10 Wireless Network not within range" >> $LOG
echo "exit 10 Wireless Network not within range" > $ERRORLOG
fi

CHECK_FOR_ERRORS

echo "Wireless network, $WIRELESSNETWORKNAME, is within range. Setup will continue..." >> $LOG

### Prompt for Mac Admin Password, Wireless Username and Wireless Password
### Applescripts perform tests for validity and return variables
echo "Prompting user for Mac Admin password..." >> $LOG
MACPASS=`osascript "$TEMP/get_mac_pass.scpt" $LOG $ERRORLOG`

CHECK_FOR_ERRORS

echo "Mac Admin Password authenticated successfully..." >> $LOG

# Remove previous database receipt to allow foo install to copy to /tmp/foo
echo $MACPASS | sudo -S pkgutil --forget edu.FooWireless.wireless.pkg

echo "Prompting user for Wireless username and password..." >> $LOG
# Change the $MBAirPresent variable to true to disable wireless network password test in applescript
WIRELESSPASS=`osascript "$TEMP/get_wireless_pass.scpt" $MACPASS $LOG $ERRORLOG $MBAirPresent`
WIRELESSUSER=`ls $TEMP | grep WirelessUserNameIs | cut -c 19-30`

### Clean up clutter from getting WirelessUserName
echo $MACPASS | sudo -S rm -rf $TEMP/WirelessUserNameIs*

CHECK_FOR_ERRORS

### Check for blank username or password
if [[ $WIRELESSPASS = "" ]] || [[ $WIRELESSUSER = "" ]] ; then
echo "Wireless username or password is blank, installation will quit" >> $LOG
osascript -e "tell application \"Finder\" to activate"
osascript -e "tell application \"Finder\" to display dialog \"The wireless username or password is blank.\" & return & return & \"The installer will now exit with an error. Please try installation again.\" buttons {\"OK\"} with icon caution"
osascript -e "tell application \"Installer\" to activate"
echo "exit 20 Wireless username or password is blank" >> $LOG
echo "exit 20 Wireless username or password is blank" > $ERRORLOG
fi

CHECK_FOR_ERRORS

### Update Log
echo "User to configure: $WIRELESSUSER" >> $LOG
if [ "$CHECKFORAIR" != "" ]; then
echo "Network Password not tested due to presence of MacBookAir hardware..." >> $LOG
else
echo "Wireless Password authenticated successfully..." >> $LOG
fi

# Get MAC Addresses
hwAddress=`ifconfig en0 | awk '/ether/ { gsub(":", ""); print $2 }'`
hwAddresswithColons=`ifconfig en0 | awk '/ether/ { gsub(":", "\\\\:"); print $2 }'`
echo "Computer Hardware address: $hwAddress" >> $LOG

AirAddress=`ifconfig $WIRELESSINTERFACE | awk '/ether/ { gsub(":", ""); print $2 }'`
AirAddresswithColons=`ifconfig $WIRELESSINTERFACE | awk '/ether/ { gsub(":", "\\\\:"); print $2 }'`
AirAddresswithColons2=`ifconfig $WIRELESSINTERFACE | awk '/ether/ { gsub(":", "\\:"); print $2 }'`
echo "Computer Airport address: $AirAddress" >> $LOG

# Get some Unique Identifiers to use in the plists...
uuid=`uuidgen`
netuuid=`uuidgen`
OLD_UUID=""

# DYNAMICALLY SET THE LEOPARD UUID FOR THE BYHOST FILE NAMING
if [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` == "00000000-0000-1000-8000-" ]]; then
LEOUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c51-62 | awk {'print tolower()'}`
elif [[ `ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-50` != "00000000-0000-1000-8000-" ]]; then
LEOUUID=`ioreg -rd1 -c IOPlatformExpertDevice | grep -i "UUID" | cut -c27-62`
fi

# Define the 4 plist files that will be changed...
PREFSPATH="/Library/Preferences/SystemConfiguration/preferences.plist"
AirportPref="/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"
EAPProfiles="$HOME/Library/Preferences/com.apple.eap.profiles.plist"
EAPBindings="$HOME/Library/Preferences/ByHost/com.apple.eap.bindings.$LEOUUID.plist"

# Turn off Airport
TOGGLEAIRPORT off

CHECK_FOR_ERRORS

##############################
##### Cleanup Section ########
##############################

###
### Search preferences.plist for matching previous wireless networks and remove if found
###

echo "Determining if previous nameofwirelessnetwork installation exists..." >> $LOG
echo "Starting Cleanup of any previously detected legacy networks..." >> $LOG

# Create a backup copy of com.apple.preferences.plist, JUST IN CASE
echo "Backing up Preferences plist file" >> $LOG
echo $MACPASS | sudo -S cp $PREFSPATH "/Library/Preferences/SystemConfiguration/preferences.plist.old"

# Search all entries in com.apple.preferences.plist to find and delete previously set connections.
# If more than 100 wireless networks present, number may
# need to be increased in COUNTER (hopefully, no one has more than 100 wireless network connections)

# Search to figure out the UUID for the SETS entry in the preferences.plist
SETUUID=`grep "/Sets/" $PREFSPATH | cut -c 16-51`

# Loop through the com.apple.preferences.plist file looking for matches of wireless networks to remove and then removing them.
for ((COUNTER=0; COUNTER > $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH
((COUNTER=COUNTER-1))
fi
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH | grep "$LEGACYNETWORK1"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $LEGACYNETWORK1 connection found and deleted" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH
((COUNTER=COUNTER-1))
fi
TESTFORNETWORK=`"$PLISTBUDDY" -c "Print :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH | grep "$LEGACYNETWORK2"`
if [ "$TESTFORNETWORK" != "" ]; then
echo "Previous $LEGACYNETWORK2 connection found and deleted" >> $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Sets:$SETUUID:Network:Interface:$WIRELESSINTERFACE:AirPort:PreferredNetworks:$COUNTER" $PREFSPATH
((COUNTER=COUNTER-1))
fi
done

###
### Delete com.apple.airport.preferences.plist file to clear previously cached settings for ALL networks (no harm done)
###

echo $MACPASS | sudo -S rm -rf $AirportPref

###
### Search EAP Profile plist to cleanup if necessary
###

# Search all entries to find and delete previously set connections. If more than 20 Enterprise
# wireless networks present, number may
# need to be increased in COUNTER (hopefully, no one has more than 20 enterprise network connections)
for ((COUNTER=0; COUNTER > $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :Profiles:$COUNTER" $EAPProfiles
((COUNTER=COUNTER-1))
fi
done

###
### Search EAP Bindings plist to cleanup if necessary
###

# Search all entries to find and delete previously set connections. If more than 20 Enterprise
# wireless networks present, number may
# need to be increased in COUNTER (hopefully, no one has more than 20 enterprise network connections)
for ((COUNTER=0; COUNTER > $LOG
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Delete :$AirAddresswithColons:$COUNTER" $EAPBindings
((COUNTER=COUNTER-1))
fi
done

##########################################
### Add entries to PLIST files section ###
##########################################

###
### Scan preferences.plist file to figure out how many entries exist under Preferred Networks
###

PLISTITEMCOUNT=-1
for ((COUNTER=0; COUNTER > $LOG
# "$PLISTBUDDY" -c "Delete :KnownNetworks" $AirportPref ;# Remove any previous entry.

echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels array" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels:0 integer 11" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels:1 integer 6" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:Remembered\ Channels:2 integer 1" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:SCAN_DIRECTED bool Yes" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:SSID_STR string $WIRELESSNETWORKNAME" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:SecurityType string WPA2\ Enterprise" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :KnownNetworks:$uuid:_timeStamp date 1995-06-21T14\:00\:00Z" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :Version integer 6" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks array" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0 dict" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0:SSID_STR string $WIRELESSNETWORKNAME" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0:SecurityType string WPA2\ Enterprise" $AirportPref
echo $MACPASS | sudo -S "$PLISTBUDDY" -c "Add :$WIRELESSINTERFACE:RecentNetworks:0:Unique\ Network\ ID string $uuid" $AirportPref

###
### Rebuild new entries for com.apple.eap.profiles.plist
###

echo "Building the User's EAPProfiles setting at $EAPProfiles..." >> $LOG

###
### Scan EAP Profile plist file to figure out how many entries exist
###

PLISTITEMCOUNT=-1
for ((COUNTER=0; COUNTER > $LOG

###
### Scan EAP Bindings plist file to figure out how many entries exist
###

PLISTITEMCOUNT=-1
for ((COUNTER=0; COUNTER > $LOG
echo $MACPASS | sudo -S security add-trusted-cert -d -r trustAsRoot -k /Library/Keychains/System.keychain $TEMP/nameofwirelessnetwork.clemson.edu.pem
echo "Certificate added successfully..." >> $LOG

# Remove any previous keychain items to clean up the keychain
echo "Checking login.keychain for previous keychain passwords to remove..." >> $LOG
osascript /tmp/foo/remove_keychain_items.scpt $MACPASS $WIRELESSNETWORKNAME $LOG $ERRORLOG

CHECK_FOR_ERRORS

echo "Finished removing previous keychain passwords" >> $LOG

# Check architecture for Intel or PowerPC hardware to determine which keychain setup command to run
HARDWARETYPE=`grep "Processor Name" $SYSTEMPROFILE | awk '{ print $3 }' `

# Add generic password item to login.keychain for network settings to attach to

$TEMP/AddKeychainItem_$HARDWARETYPE $HOME $WIRELESSUSER $WIRELESSPASS $uuid $LOG $ERRORLOG

CHECK_FOR_ERRORS

# Report Password item added successfully to log
echo "Keychain Password Item added successfully..." >> $LOG

### Turn on Wireless
TOGGLEAIRPORT on

CHECK_FOR_ERRORS

echo "Wireless Setup completed successfully" >> $LOG

# Remove all setup files when finished
echo $MACPASS | sudo -S rm -rf /tmp/foo

exit 0

Applescript Section:

There are three applescripts, used to obtain and test usernames and passwords, and cleanup Keychain Items, that are called by the Main Script. These feed back the variables for username and password to the parent script.

get_mac_pass.scpt

The Mac password cannot be blank (I wouldn’t recommend a user have a blank password anyway) nor can it contain a space (causes problems with the script).
-- Script created for
-- by Bryan S. Lee 2009

-- This script will prompt user for the Admin Mac Password and test the password for validity
-- This script expects to receive all logs locations from the parent script

on run argv
set LOGS to item 1 of argv
set ERRORLOG to item 2 of argv
set theUser to (do shell script "echo $USER")
set myMacPass to ""
set myMacPassTest to ""
set illegalChar to " "

-- Prompt user for Mac Password
tell application "Finder"
activate
repeat until myMacPassTest is not ""
set myMacPassDialog to display dialog "Please enter your Mac password." & return & "(This is the password you created while registering your Mac)" default answer "" buttons {"Quit", "OK"} default button 2 with title " Wireless Setup" with hidden answer
set myMacPass to the text returned of myMacPassDialog
if button returned of myMacPassDialog is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
tell application "Installer" to activate
return
end tell
end if
-- Test to see if Mac Password is correct
tell me
try
do shell script "sudo touch /private/tmp/mac_password_test" user name theUser password myMacPass with administrator privileges
if every character of illegalChar is in myMacPass then
tell application "Finder"
activate
tell me
do shell script "echo \"exit 97 Cancelled installation due to an illegal character in the Mac password.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 97 Cancelled installation due to an illegal character in the Mac password.\" 2>&1 >> " & LOGS
end tell
set dialogReply to display dialog "Your Mac password contains an illegal character." & return & return & "You MUST change your Mac password to continue using this installer." & return & return & "Please change your Mac Password by clicking the 'Change Mac Password' button below. Then click the 'Change Password' button that appears in the next window." & return & return & "This installer will now exit with an error. Please run it again after changing your Mac Password." with title " Wireless Setup" buttons {"Quit", "Change Mac Password"} default button 2 with icon caution
tell application "Installer" to activate
set myMacPassTest to ""
if button returned of dialogReply is "Change Mac Password" then
tell application "System Preferences"
activate
reveal anchor "passwordPref" of pane "Accounts"
activate pane id "com.apple.preferences.users"
end tell
end if
return
end tell
end if
if myMacPass is "" then
tell application "Finder"
activate
tell me
do shell script "echo \"exit 98 Cancelled installation due to blank Mac password.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 98 Cancelled installation due to blank Mac password.\" 2>&1 >> " & LOGS
end tell
set dialogReply to display dialog "It is HIGHLY recommended that your Mac Password not be blank due to security concerns." & return & return & "You MUST create a Mac password to continue using this installer." & return & return & "Please create a Mac Password by clicking the 'Create Mac Password' button below. Then click the 'Change Password' button that appears in the next window." & return & return & "This installer will now exit with an error. Please run it again after creating a Mac Password." with title " Wireless Setup" buttons {"Quit", "Create Mac Password"} default button 2 with icon caution
tell application "Installer" to activate
set myMacPassTest to ""
if button returned of dialogReply is "Create Mac Password" then
tell application "System Preferences"
activate
reveal anchor "passwordPref" of pane "Accounts"
activate pane id "com.apple.preferences.users"
end tell
end if
return
end tell
end if
set myMacPassTest to "true"
on error
tell application "Finder"
activate
set dialogReply to display dialog "Mac Password entered was incorrect, please try again." with title " Wireless Setup" buttons {"Quit", "OK"} default button 2 with icon caution
set myMacPassTest to ""
if button returned of dialogReply is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
tell application "Installer" to activate
return
end tell
end if
end tell
end try
end tell
end repeat
end tell

-- cleanup password test file
do shell script "sudo rm -rf /private/tmp/mac_password_test" user name theUser password myMacPass with administrator privileges

-- Bring Installer.app to frontmost
tell application "Installer" to activate

return myMacPass
end run

get_wireless_pass.scpt
-- Script created for Clemson University
-- by Bryan S. Lee 2009

-- Prompt for Network username and password. Write username to a file and return the password to the main script
-- This script expects to receive the Mac Admin password, Logs locations and MBAirPresent variable from the parent script as arguments
-- Ex. osascript /path/to/this/script $MACPASS $LOG $ERRORLOG $MBAirPresent

on run argv
set myMacPass to item 1 of argv
set LOGS to item 2 of argv
set ERRORLOG to item 3 of argv
set MBAirPresent to item 4 of argv
set theUser to (do shell script "echo $USER")
set myPass to ""
set counter to 1
set serverMount to ""

tell application "Finder"
with timeout of 10000 seconds
activate
repeat until myPass is not ""
if counter &1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
end tell
tell application "Installer" to activate
return
end if
if button returned of acctBox is "OK" then
if myAcct is not "" then

-- Remove any trailing @mydomain.com information from network name
if myAcct contains "@" then
set myAcct to text 1 through ((offset of "@" in myAcct) - 1) of myAcct
end if

-- Test to see if Network password is correct
set myPassBox to display dialog "Please enter your Clemson University password:" & return & return & "Be careful to enter it correctly!" & return & "This password is case-sensitive!" default answer "" buttons {"Quit", "OK"} default button 2 with title "Clemson University Wireless Setup" with hidden answer
if button returned of myPassBox is "Quit" then
tell me
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 99 User cancelled installation.\" 2>&1 >> " & LOGS
end tell
tell application "Installer" to activate
return
end if
set myPass to the text returned of myPassBox

-- test to see if network password is blank
if myPass is not "" then

-- Convert any illegal symbols in password to hexadecimal to function correctly in URL of Volume mount test
try
tell me
set fixedPassword to do shell script "python -c 'import sys, urllib; print urllib.quote(sys.argv[1])' " & quoted form of myPass
end tell
on error
tell me
do shell script "echo \"exit 90 Password possibly contains unsupported characters, such as backslash or double quotes. Please reset password and try again.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 90 Password possibly contains unsupported characters, such as backslash or double quotes. Please reset password and try again.\" 2>&1 >> " & LOGS
end tell
tell application "Finder"
activate
set dialogReply to display dialog "Password possibly contains unsupported characters, such as backslash or double quotes. Please reset password and try again." & return & return & "Click the RESET PASSWORD button to be sent to the Password Reset Webpage." buttons {"Reset Password", "Quit"} default button 1 with icon caution
if button returned of dialogReply is "Reset Password" then
open location "https://login.clemson.edu/changepass.php"
end if
end tell
tell application "Installer"
activate
end tell
return
end try

-- Test to see if Network Password is correct

if MBAirPresent is "false" then
tell me
try
set serverMount to "software"
do shell script "sudo mkdir '/Volumes/software'" user name theUser password myMacPass with administrator privileges
do shell script "sudo mount_smbfs '//" & myAcct & ":" & fixedPassword & "@software.clemson.edu/software' /Volumes/software/" user name theUser password myMacPass with administrator privileges
on error

-- If can't connect to first server, try a second just to be sure in case first server is down...

do shell script "sudo rmdir /Volumes/software/" user name theUser password myMacPass with administrator privileges
try
set serverMount to "share"
do shell script "sudo mkdir '/Volumes/share'" user name theUser password myMacPass with administrator privileges
do shell script "sudo mount_smbfs '//" & myAcct & ":" & fixedPassword & "@share.clemson.edu/share' /Volumes/share/" user name theUser password myMacPass with administrator privileges
on error
do shell script "sudo rmdir /Volumes/share/" user name theUser password myMacPass with administrator privileges
set myPass to ""
if counter < 3 then
set retries to (3 - counter)
if retries &1 >> " & LOGS
end if
end try
end try
end tell
end if
else
display dialog "Clemson University password cannot be blank!" buttons {"OK"} default button 1 with icon caution
end if
else
display dialog "Clemson University username cannot be blank!" buttons {"OK"} default button 1 with icon caution
end if
end if
else
tell me
do shell script "echo \"exit 2 Password not accepted by network.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 2 Password not accepted by network.\" 2>&1 >> " & LOGS
end tell
tell application "Finder"
activate
set dialogReply to display dialog "Password is not accepted. Possibly due to a case-sensitivity difference. The wireless installer will now exit with an error." & return & return & "Please reset your password and try again." & return & return & "Click the RESET PASSWORD button to be sent to the Password Reset Webpage." buttons {"Reset Password", "Quit"} default button 1 with icon caution
if button returned of dialogReply is "Reset Password" then
open location "https://login.clemson.edu/changepass.php"
end if
set myPass to "exit_loop"
end tell
tell application "Installer"
activate
end tell
return
end if
set counter to counter + 1
end repeat
end timeout
end tell
delay 0.5
if MBAirPresent is "false" then
try
if serverMount is "software" then
do shell script "sudo umount /Volumes/software/" user name theUser password myMacPass with administrator privileges
end if
if serverMount is "share" then
do shell script "sudo umount /Volumes/share/" user name theUser password myMacPass with administrator privileges
end if
on error
tell me
do shell script "echo \"exit 3 Could not unmount network test drive.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 3 Could not unmount network test drive.\" 2>&1 >> " & LOGS
end tell
tell application "Finder"
activate
display dialog "Could not disconnect network drive during network password test" buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end try
end if

-- Write username to file for parent script to pickup
if myAcct is not "" then
tell me
do shell script "touch /private/tmp/cu_wireless/WirelessUserNameIs" & myAcct user name theUser password myMacPass with administrator privileges
end tell
end if
if myAcct is "" then
tell me
do shell script "echo \"exit 21 Wireless username is blank. Unknown error.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 21 Wireless username is blank. Unknown error.\" 2>&1 >> " & LOGS
end tell
tell application "Finder"
activate
display dialog "Wireless username is blank. Unknown error." & return & return & "Please try running the Wireless Installer again." buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end if
tell application "Installer"
activate
end tell

-- Send wireless password to parent script
return myPass

end run

remove_keychain_items.scpt

Some items in this portion need to be edited manually (Names of keychain items). Also, if the keychain is locked with a different password than the main user account password, the script will error at this step.
-- Script created
-- by Bryan S. Lee 2009

-- This script will remove all necessary keychain items.
-- This includes previous keychain entry and legacy network keychain items.
-- Then it will add the new keychain item
-- Removal Section of script should be edited with the names of the keychains you wish to be removed

-- IMPORTANT INFO!!!
-- This script expects to receive the following as arguments directly following the command:
-- Mac Administrative password
-- Name of the wireless

-- Like the sample below
-- osascript path_to_this_script.scpt MacPassword WirelessName

on run argv
-- set incoming variables
set MacPassword to item 1 of argv
set WirelessName to item 2 of argv
set LOGS to item 3 of argv
set ERRORLOG to item 4 of argv

-- Set other variables
set KeychainName to "WPA: " & WirelessName

-- ******
-- Removal Section (PLEASE EDIT AS NECESSARY)
-- ******

try
tell application "Keychain Access"
quit
end tell
tell application "Keychain Scripting"
tell keychain "login.keychain"
unlock with password MacPassword
repeat 5 times -- to catch possible, multiple keychain items with same name
repeat with this_key in (get keys)
if (get name of this_key) = KeychainName then
do shell script "echo \"Keychain item, NewWirelessNetwork, found...\" 2>&1 >> " & LOGS
delete this_key
do shell script "echo \"Keychain item, NewWirelessNetwork, deleted...\" 2>&1 >> " & LOGS
exit repeat
end if
end repeat
repeat with this_key in (get keys)
if (get name of this_key) = "Network password for NewWirelessNetwork Profile" then
do shell script "echo \"Keychain item, Network password for NewWirelessNetwork Profile, found...\" 2>&1 >> " & LOGS
delete this_key
do shell script "echo \"Keychain item, Network password for NewWirelessNetwork Profile, deleted...\" 2>&1 >> " & LOGS
exit repeat
end if
end repeat
repeat with this_key in (get keys)
if (get name of this_key) = "cuairnet" then
do shell script "echo \"Keychain item, LegacyNetwork, found...\" 2>&1 >> " & LOGS
delete this_key
do shell script "echo \"Keychain item, LegacyNetwork, deleted...\" 2>&1 >> " & LOGS
exit repeat
end if
end repeat
end repeat
end tell
end tell
on error
do shell script "echo \"exit 4 Error attempting to remove previous wireless keychain items. Probably due to a locked login.keychain. Please manually unlock the login.keychain using the Keychain Access application and try again.\" 2>&1 > " & ERRORLOG
do shell script "echo \"exit 4 Error attempting to remove previous wireless keychain items. Probably due to a locked login.keychain. Please manually unlock the login.keychain using the Keychain Access application and try again.\" 2>&1 >> " & LOGS
tell application "Finder"
activate
display dialog "Error attempting to remove previous wireless keychain items. Probably due to a locked login.keychain." & return & return & "Please manually unlock the login.keychain using the Keychain Access application and run the wireless installer again." & return & return & "This installer will now exit with an error." buttons {"OK"} default button 1 with icon caution
end tell
tell application "Installer"
activate
end tell
return
end try
end run

C Programming Section:

This section replaced the part that would actually set the access level for the wireless to get to the keychain item. Before it used GUI Applescript and relied on Assistive Devices to be able to click a single ‘OK’ button. Using C to create the keychain item and set the ACL to allow the eapolclient to access the keychain fixes the issues with doing it the previous way.

This C code should be compiled for both Intel and PowerPC separately and the resulting files should be named:
AddKeychainItem_Intel
AddKeychainItem_PowerPC

The parent script determines the processor type and will run the appropriate version of the executable.

You would need to do a find/replace in this section of code for wirelessnetworkname and put in the name of your particular wireless network.

AddKeychainItem.m
#import
#import
#import
#import

int main(int argc, const char * argv[]) {
if(argc < 7) {
// missing arguments
return 1;
}
int ret_code = 0;
int printed = 0;

char keychain_path[strlen(argv[1]) + 33];
strcpy(keychain_path, argv[1]);
char username[strlen(argv[2])];
strcpy(username, argv[2]);
char password[strlen(argv[3])];
strcpy(password, argv[3]);
char unique_uid[strlen(argv[4])];
strcpy(unique_uid, argv[4]);
FILE *log;
log = fopen(argv[5], "a+");
FILE *error_log;
error_log = fopen(argv[6], "a+");

// make sure we are using this user's login.keychain
SecKeychainRef login_chain;

// I can haz keychain access?
strcat(keychain_path, "/Library/Keychains/login.keychain");
OSStatus status_0 = SecKeychainOpen(keychain_path, &login_chain);
SecKeychainStatus keychainStatus;
SecKeychainGetStatus(login_chain, &keychainStatus);

if(status_0 != noErr) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "COULD NOT FIND LOGIN.KEYCHAIN");
fprintf(error_log, "COULD NOT FIND LOGIN.KEYCHAIN");
ret_code = 1;
goto end3;
}
if((keychainStatus & kSecUnlockStateStatus) == 0) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "KEYCHAIN LOCKED");
fprintf(error_log, "KEYCHAIN LOCKED");
ret_code = 1;
goto end3;
}
if((keychainStatus & kSecReadPermStatus) == 0) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "KEYCHAIN NOT READABLE");
fprintf(error_log, "KEYCHAIN NOT READABLE");
ret_code = 1;
goto end3;
}
if((keychainStatus & kSecWritePermStatus) == 0) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "KEYCHAIN NOT WRITABLE");
fprintf(error_log, "KEYCHAIN NOT WRITABLE");
ret_code = 1;
goto end3;
}

// check for an existing key by the name "WPA: wirelessnetworkname"
SecKeychainSearchRef search;
SecKeychainItemRef found_item;
int found = 0;

SecKeychainAttribute att[3];
SecKeychainAttributeList list;
att[0].tag = kSecAccountItemAttr;
att[0].data = username;
att[0].length = strlen(att[0].data);
att[1].tag = kSecDescriptionItemAttr;
att[1].data = "Internet Connection";
att[1].length = strlen(att[1].data);
att[2].tag = kSecLabelItemAttr;
att[2].data = "WPA: wirelessnetworkname";
att[2].length = strlen(att[2].data);

list.count = 3;
list.attr = att;

status_0 = SecKeychainSearchCreateFromAttributes(login_chain, kSecGenericPasswordItemClass, &list, &search);
while(SecKeychainSearchCopyNext(search, &found_item) == noErr) {
found = 1;
CFRelease(found_item);
}
if(found == 1) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "KEYCHAIN ITEM ALREADY EXISTS");
fprintf(error_log, "KEYCHAIN ITEM ALREADY EXISTS");
ret_code = 1;
goto end3;
}
// create the SecKeychainItemRef object
SecKeychainItemRef itemRef;

// create the SecTrustedApplicationRef
SecTrustedApplicationRef apps[] = {NULL};
CFArrayRef trustedList;
OSStatus status_1;
char *eapo_path = "/System/Library/SystemConfiguration/EAPOLController.bundle/Resources/eapolclient";
char *eapo_path_snow_leopard = "/System/Library/SystemConfiguration/EAPOLController.bundle/Contents/Resources/eapolclient";
FILE *eapo_ref = fopen(eapo_path, "r");
if(eapo_ref == NULL) {
status_1 = SecTrustedApplicationCreateFromPath(eapo_path_snow_leopard, &apps[0]);
} else {
status_1 = SecTrustedApplicationCreateFromPath(eapo_path, &apps[0]);
}
if(status_1 != noErr) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "COULD NOT CREATE TRUSTED APPLICATION OBJECT");
fprintf(error_log, "COULD NOT CREATE TRUSTED APPLICATION OBJECT");
ret_code = 1;
goto end2;
}

if((trustedList = CFArrayCreate(NULL, (const void **)apps, 1, &kCFTypeArrayCallBacks)) == NULL) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "COULD NOT CREATE TRUSTED APPLICATION ARRAY");
fprintf(error_log, "COULD NOT CREATE TRUSTED APPLICATION ARRAY");
ret_code = 1;
goto end2;
}

// create the access object (remember to CFRelease "accessRef")
SecAccessRef accessRef = nil;
OSStatus status_2 = SecAccessCreate(CFSTR("WPA: wirelessnetworkname"), trustedList, &accessRef);
if(status_2 != noErr) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "COULD NOT CREATE ACCESS OBJECT");
fprintf(error_log, "COULD NOT CREATE ACCESS OBJECT");
ret_code = 1;
goto end1;
}

OSStatus status_3 = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &list, strlen(password), &password[0], login_chain, accessRef, &itemRef);
if(status_3 != noErr) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "COULD NOT CREATE KEYCHAIN ITEM");
fprintf(error_log, "COULD NOT CREATE KEYCHAIN ITEM");
ret_code = 1;
goto end1;
}

// can't add a service or comment tag until after you CREATE the keychain item... LAME
SecKeychainAttribute att2[2];
SecKeychainAttributeList list2;
list2.count = 2;
att2[0].tag = kSecServiceItemAttr;
att2[0].data = unique_uid;
att2[0].length = strlen(att2[0].data);
att2[1].tag = kSecCommentItemAttr;
att2[1].data = "Wireless Installer created and maintained by Bryan S. Lee and Kimberly Roche.";
att2[1].length = strlen(att2[1].data);
list2.attr = att2;

OSStatus status_4 = SecKeychainItemModifyAttributesAndData(itemRef, &list2, 0, NULL);
if(status_4 != noErr) {
if(printed == 1) { fprintf(log, " / "); fprintf(error_log, " / "); }
else { fprintf(log, "exit 5 ERROR: "); fprintf(error_log, "exit 5 ERROR: "); }
printed = 1;
fprintf(log, "COULD NOT APPEND TO KEYCHAIN ITEM");
fprintf(error_log, "COULD NOT APPEND TO KEYCHAIN ITEM");
ret_code = 1;
goto end1;
}

end1:
if(accessRef) CFRelease(accessRef);
end2:
if(itemRef) CFRelease(itemRef);
end3:
if(ret_code == 0) {
fprintf(log, "KEYCHAIN ITEM SUCCESSFULLY ADDED...\n");
} else {
fprintf(log, "\n");
fprintf(error_log, "\n");
}

fclose(log);
fclose(error_log);

return ret_code;
}

Hopefully the new and improved version (which is still not 100% complete, but getting closer) will help someone out there. If so, drop a comment.

But who would be the Best Man?

Posted August 25, 2009 by bigmaconcampus
Categories: Rhinoism

Tags: , , , ,

While making lasagna with Rhino one evening, I let her take a nip at the mozzarella and she commented:

“Mmmmmm, I’m going to have to marry that cheese some day.”

Windows OS installer for Mac

Posted August 20, 2009 by bigmaconcampus
Categories: Mac Tech

Tags: , , , , , , , , , , , , , , , , , , ,

As part of a group of installers I’ve developed for our University, the one that I thought would be the most difficult, but turned out to be the easiest was the one that will install a Windows OS as a dual-boot on the Mac.

This is not necessarily a fully automated method (like I would use in a lab situation), but rather an easy to use installer that can be posted on a intranet website for student (primarily students), faculty, employee use. It allows us to put Windows on Macs that are not our property and therefore we don’t have admin rights on the machine.

This is a flat-package (.pkg) that contains the necessary scripts to download a Windows image (created with Winclone) via curl, partitions the hard drive (35 GB partition) and then clones the downloaded image onto the second partition that was just created. All the user does is click a few buttons and the installation is fully automated. The installer package is relatively small at around 1 MB. The heavy lifting is done by the script downloading the image file to a /tmp location during the installation.

With the second version, an overlay window was added (using iHook) that allows a progress bar to give the user some feedback as to the status of the installation. We found some people were getting impatient and shutting off their computers thinking that the installation had frozen (Total time for this part was about 20-30 minutes), which was necessitating the need for better user feedback.

Also found that the image for Windows Vista needed to be sysprepped to function with all the varying Apple hardware. Unfortunately, this doubles the installer time. Sysprep takes about 20-30 minutes to do it’s thing. And reboots several times as well. But it is worth it to have a single image work on the varying Apple hardware. The image also had to move through the various hardwares starting from oldest to newest to load all of the bootcamp drivers. Doing it in a different order tended to kill Vista. Hopefully things will be smoother with Windows 7.

We have plans to make the third version use a bit torrent to download the image rather than curling the file from a single webserver. The beating the server takes during student setup workshops is heavy (20-50 user’s all trying to download the same 6.5 GB file at the same time). Switching to a torrent based download should relieve the server strain and speed up the download time for the clients when a large number run it simultaneously.

Here are the main scripts that performs all the tasks. It is kicked off as a postscript from a Packagemaker flat-package that is downloaded from a internal website (on purpose to keep the rest of the world from being able to access it). The package includes the Winclone command-line pieces necessary for cloning, but not the actual image file. That is downloaded separately by the script. iHook is also included in the package for the feedback.

Postscript for Package

#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

### This postinstall script will kick start the actual Vista
### Installer script and Feedback window to show progress

/private/tmp/foo/iHook/iHook.app/Contents/MacOS/iHook --no-titlebar --script=/private/tmp/foo/windowsvista/vista_installer.sh

ERROR=`grep ERROR /Library/Logs/Vista_Installer_For_Mac.log | cut -c 1-6`
if [ "$ERROR" != "" ]; then
rm -rf /tmp/clemson
$ERROR
fi

exit 0

The first line engages the main script. The ERROR section is just a test for any errors that might have occurred so that the installer will error properly if there was an error deeper in the other script. Found it was the easiest way to communicate between the installer app, iHook, and the nested scripts. The installer has a tendency to exit successful even when an error occurs if this part is left out.

Main Script referred to in the previous postscript that is run by iHook (vista_installer.sh):

#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin export PATH

### Script created by Bryan Lee,
### April 2008.
### Modified November 2008 for new Apple hardware and
### to add the feedback mechanism.
###
### This postinstall script downloads the Windows image files
### in the proper temp directory and sets the correct permissions.
### Then partition the hard drive into 2 partitions. Finally, clone
### the Windows image onto the 2nd partition.
###
### iHook is used to give feedback to the user during the process.
###
### Requires iHook be installed in the /tmp directory
### Requires Winclone.perl be modified to redirect stderr to
### PROGRESS_FILE path during the restore process
### like the following example:
###
### do_command("=====restoring image======","/usr/bin/gunzip -c \
### "${image_dir}/boot.img.gz\"| \"$ntfstools_dir/ntfsclone\"
### --restore-image --overwrite \"$ntfs_partition\" - 2>&1 >
### /private/tmp/foo/windowsvista/winclone_progress.txt");
###
### Depends on Package installer to download Windows image file
### to /tmp directory
###

# Setup Location of Log file
LOG="/Library/Logs/Vista_Installer_For_Mac.log"

# Setup initial state for iHook Window
echo "%LOG OPEN" $LOG
chmod a+r $LOG
echo "%BECOMEKEY"
# echo "%TITLE Windows Vista Installer for Macintosh"
echo "%WINDOWLEVEL HIGH"
echo "%WINDOWSIZE 800 600"
echo "%WINDOWPOSITION CENTER"
echo "%WINDOWZOOM ENABLE"
echo "%HIDETIMER"
echo "%BACKGROUND /private/tmp/foo/iHook/windowsvistaformac_background.jpg"
echo "%BACKGROUNDSCALING TOFIT"

### Cleanup any possible files leftover from a previous run of the installer
### that would cause issues if present
rm -rf /private/tmp/foo/windowsvista/boot.img.gz
rm -rf /private/tmp/foo/windowsvista/winclone_progress.txt

### Set initial blank variables
PROGRESS=""
IHOOK_PERCENT=""
DOWNLOAD_PERCENT=""
PREVIOUS_FILE_SIZE=""
CURRENT_FILE_SIZE=""
KILL_CURL=""
SECOND_PARTITION_NAME=""

#####################
### FUNCTIONS ###
#####################

# Function for making computer beep three times
BEEP_THREE_TIMES ()
{
LIMIT=3 # Upper limit
a=0
while [ $a -le "$LIMIT" ]; do
a=$(($a+1))
echo "%BEEP"
sleep .5
done
}

### Set PID of iHook (to kill) in case of error
KILL_IHOOK=`ps acx | grep iHook | cut -c 1-5`

### Must set the size of this variable to the size of the image file in Kilobytes
### Using the following command on the image directory
### ls -sk | grep total | cut -c 7-15
### Current values for Vers2 is 6734820. Round down to the nearest MB
TOTAL_SIZE="6734000"

### Must set the path to the file that contains the progress from Winclone
PROGRESS_FILE="/private/tmp/foo/windowsvista/winclone_progress.txt"

#####################
### Initial tests ###
#####################

### Test for Processor type ###
HARDWARETYPE=`system_profiler -detailLevel mini | grep "Processor Name" | awk '{ print $3 }' `
if [ "$HARDWARETYPE" != "Intel" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 9, ERROR: Computer Hardware Cannot support Windows"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"This computer does not support running Windows because is does not have an Intel Processor.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 9
fi

# Check to see if a second partition already exists, or some other odd situation
SECOND_PARTITION_NAME=`df | grep /dev/disk0s3`
if [ "$SECOND_PARTITION_NAME" != "" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 8, ERROR: Multiple Partitions Exist"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"Multiple Partitions Already Exist\" & return & \"This installer can not be run on this system without removing the secondary partition\" & return & return & \"Please contact Jenny at 867-5309.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 8
fi

### DOWNLOAD STAGE 1 ###

# Start Progress Bar for Downloading Image
echo "%BEGINPOLE"
echo "Downloading Windows Image"

### Change directory to the Windows temp directory created by the installer
### and set the current file size variable

cd /private/tmp/foo/windowsvista/
CURRENT_FILE_SIZE=$(ls -sk | grep total | cut -c 7-15)

### Download image needed for Windows imaging from the Web server
echo "Starting Download of Windows image"
curl -O http://www.foo.edu/windows/vista/version2/boot.img.gz &

### Loop to update download progress constantly until complete
until [ "$CURRENT_FILE_SIZE" -ge "$TOTAL_SIZE" ]; do
sleep 7
DOWNLOAD_PERCENT=`echo "($CURRENT_FILE_SIZE * 100) / $TOTAL_SIZE" | bc`
echo "%$DOWNLOAD_PERCENT"
echo "Download Is $DOWNLOAD_PERCENT Percent Complete"
CURRENT_FILE_SIZE=$(ls -sk | grep total | cut -c 7-15)
if [ "$PREVIOUS_FILE_SIZE" = "$CURRENT_FILE_SIZE" ]; then
BEEP_THREE_TIMES
echo "%ENDPOLE"
echo "%WINDOWLEVEL NORMAL"
echo "exit 1, ERROR: Image file did not download successfully"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"An error has occurred while attempting to download the Windows Image File.\" & return & return & \"Please verifiy your network connection and try the installation again.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
KILL_CURL=`ps acx | grep curl | cut -c 1-5`
kill $KILL_CURL
kill $KILL_IHOOK
exit 1
fi
PREVIOUS_FILE_SIZE=$CURRENT_FILE_SIZE
done

echo "%100"
echo "Download Is 100 Percent Finished"
sleep 2

echo "%ENDPOLE"

### Set correct permissions on script files

chmod u+rwx /private/tmp/foo/windowsvista/winclone.perl
chmod u+rwx /private/tmp/foo/windowsvista/gptrefresh
chmod u+rwx /private/tmp/foo/windowsvista/ntfsclone
chmod u+rwx /private/tmp/foo/windowsvista/ntfscp
chmod u+rwx /private/tmp/foo/windowsvista/ntfsresize
chmod u+rwx /private/tmp/foo/windowsvista/size
chmod u+rwx /private/tmp/foo/windowsvista/BCD
chmod u+rwx /private/tmp/foo/windowsvista/boot.mbr
chmod u+rwx /private/tmp/foo/windowsvista/partitionid
chmod u+rwx /private/tmp/foo/windowsvista/description
chmod u+rwx /private/tmp/foo/windowsvista/vista_installer.sh

### PARITIONING STAGE 2 ###

### Properties ###
#
# These items must be modified to suit your environment before
# implementing this script! You do not need to make any other
# modifications to this file than these properties.
# Note: the target disk is determined programatically by finding
# the internal drive that is already partitioned using the GPTFormat
# If you have multiple drives (physical drives, not partitions)
# attached to your client machines that are partitioned using the
# GPTFormat, you will need to specify the target disk manually.

echo "Partitioning Drive. Please be patient."
sleep 2

# Partition the internal disk that is already using the GPT partitioning scheme
tdisk=`diskutil list | awk '/GUID_partition_scheme/ {print $NF}'`
totalSize=`df -m | awk "/$tdisk/"' {total+=$2} END {print total}'`
macSize=$(($totalSize - 35000))
diskutil resizeVolume /dev/$tdisk"s2" ${macSize}M MS-DOS WINDOWS 0b

### Check to see if 2nd parition was created
SECOND_PARTITION_NAME=`df | grep /dev/disk0s3 | grep "WINDOWS"`

if [ "$SECOND_PARTITION_NAME" = "" ]; then
BEEP_THREE_TIMES
echo "%WINDOWLEVEL NORMAL"
echo "exit 2, ERROR: Paritioning failed"
osascript -e "tell application \"iHook\" to activate"
osascript -e "tell application \"iHook\" to display dialog \"Partitioning was not successful! \" & return & return & \"Possible causes include: \" & return & \"More than one partition already exists\" & return & \"An external hard drive is connected\" & return & \"A rare issue with the Partition Map of the hard drive\" & return & return & \"Please try installation again or contact Jenny at 867-5309.\" & return & return & \"This installation will now exit with an error.\" buttons {\"OK\"} default button 1 with icon caution with title \"Windows Vista Installer for Mac\""
osascript -e "tell application \"Installer\" to activate"
kill $KILL_IHOOK
exit 2
fi

echo "Partitioning Completed Successfully"
sleep 1

### CLONING STAGE 3 ###

# Start Progress Bar for Cloning
echo "%BEGINPOLE"
echo "Cloning Process Is Starting"
sleep 1
### Begin the Windows cloning process onto the 2nd partition

/private/tmp/foo/windowsvista/winclone.perl --self-extract &

### Find initial progress from the winclone output
touch $PROGRESS_FILE
PROGRESS=$(tail -1 $PROGRESS_FILE)

### Loop to keep temp file location from showing in feedback window
LIMIT=14 # Upper limit
a=0

while [ $a -le "$LIMIT" ]
do
a=$(($a+1))
echo "Cloning Operation Is Starting"
sleep .5
done

### Loop to update cloning progress constantly until complete
until [ "$PROGRESS" = '100.00 percent completed' ]; do
IHOOK_PERCENT=$(tail -1 $PROGRESS_FILE | cut -c 1-3)
echo "%$IHOOK_PERCENT"
echo "Cloning Operation Is $IHOOK_PERCENT Percent Complete"
PROGRESS=$(tail -1 $PROGRESS_FILE)
sleep 3
done

echo "%100"
echo "Cloning Operation Is 100 Percent Finished"
sleep 5

echo "%ENDPOLE"
echo "Finishing Installation"
sleep 5

echo "Installation of Windows Vista completed"
sleep 5

echo "Cleaning up installation files"
sleep 5

rm -rf /private/tmp/foo
echo "Installation Completed Successfully"
sleep 2

exit

The script checks for Intel-processor, that the initial state has only one partition, that the download completes, and that partitioning was successful or else gives an error dialog and then exits.

There are two odd glitches that occur about 1 in 100 installations, both dealing with partition map issues.

The first will cause the partitioning stage to error. Seems that on the occasional Mac, there is a small error in the partition map that doesn’t rear it’s ugly head until you attempt to change the partitions. The only fix seems to be to boot from a Disk Warrior CD and rebuild. Then the installer will run fine.

The second issue is a little more frustrating and is documented by Apple. The installation will finish without any problems, but upon the first boot while holding down the ‘option’ key, the Mac won’ recognize that the Windows partition is bootable. The Startup Disk Panel will show it, all the files are on the second partition, but the Mac refuses to boot to it. Sometimes removing the partition and re-running the installer will work, sometimes not. Doing a manual clone using Winclone will usually work. Apple’s suggestion is to erase the partition and start over.

Hope this helps someone out there with any deployment problems or if they are just looking for ideas.

Reset Mac Password the Easy Way

Posted July 5, 2009 by bigmaconcampus
Categories: Mac Tech

Tags: , , , , , ,

We are swimming in the middle of summer workshops at our University. We do these a couple of times a week and the purpose is to help introduce the new, incoming students to University specific systems, setup wireless for the school and install software. We even offer Windows for the few that might want it. All this in less than 2 hours.

A good time is had by all…

One of the problems we run into regularly is the one in 50 students that either can’t remember their Mac password (even though we ask them to try and guess it about 10 times). Or better yet, the parental units, being helpful, did the original setup for the child they love instead of letting them gain some independence and do it themselves, thereby screwing them over in their first college experience. But I digress.

When we run into this situation, we need to reset their password quickly and painlessly. Not always having installation discs handy, we resort to doing it in Single-User mode.

To do this, reboot the computer holding down the command (Apple symbol on older Macs) and ‘S’ key at the same time. After about 10 seconds or so, you’ll see a very Unix-y OS loaded. You may want to hit return a couple of times to make sure it has finished loading.

WARNING: Doing the next part will cause you to lose any saved passwords in your Keychain. If you are locked out of the Mac anyway, you really have nothing to lose though.

At this point, you have booted the computer as root and need to run the following commands:

mount -uw /
launchctl load

/System/Library/LaunchDaemons/com.apple.DirectoryServices.plist

ls /Users (to get the username to reset)

passwd username (username being the username you are resetting)

reset password (password being the new password)

rm -rf /Users/username/Library/Keychains/login.keychain

reboot

After the computer reboots, you should be able to login using the new password now. Be aware, that the system will create a new login.keychain for you with no passwords in it. You can force this creation immediately by opening Safari.

p.s. This method only works on Leopard 10.5.x.

iPhone Sent Items Issue with Entourage 2008

Posted July 2, 2009 by bigmaconcampus
Categories: Mac Tech

Tags: , , , , , , , ,

UPDATE 8-20-2009:
Seems that the iPhone OS 3.1 update fixed this issue. So the following info might be moot at this point.

Ever since using my iPhone with Exchange (since the iPhone 2.0 Beta program), I’d had an issue with how the Sent Items from the iPhone device show in the Exchange Sent Items when viewed from Entourage 2008 (think it’s a problem with Entourage 2004 also, if I’m remembering correctly). Messages that are sent, show with no subject and the message content displays in HTML code or MIME encoded making it unreadable by the user.

After originally blaming the iPhone for this new behavior at the time (issue wasn’t present when connecting to Exchange via IMAP), I narrowed it down to an issue between ActiveSync and Entourage (wonderfully, both being Microsoft Products). I’ve since seen the issue with a Palm Treo running Windows CE that also uses ActiveSync to connect to Exchange and the user uses Entourage 2008.

Anyway, never having seen the problem fixed, about a year ago I came up with a work-around to make Entourage at least ’seem’ to behave as you’d expect. A couple of Exchange Rules can be created to manipulate the messages around to end up doing what you’d expect.

This relies on having some unique text in your iPhone signature to identify emails coming from the device. Something like “Sent via iPhone” would do the trick. Also, the iPhone (or other device) should be set to BCC all sent messages to your email address. Entourage will then be able to determine which messages come from you from the device and move the appropriately using the following two rules:

ActiveSync Sent Items Fix

ActiveSync Sent Items Fix

ActiveSync Sent Items Cleanup

ActiveSync Sent Items Cleanup

Make sure that the rules have been added to the Exchange tab in the Entourage Rules section and are enabled and that should do it. Keep in mind that this is a local client rule and won’t take affect until the messages are downloaded onto the Mac running the rules. The side-effect of this is that you’ll receive a copy of all sent emails on your iPhone if your Mac is not open and able to apply the rules, but once you open Entourage, it will move everything around to its proper place and everything will eventually work out.

iPhone 3.0 Thoughts, Bugs & Complaints

Posted June 18, 2009 by bigmaconcampus
Categories: Mac Tech

Tags: , , , , , , , ,

Ok, after playing with the new iPhone/iPod Touch 3.0 OS, I’ve come across a few items.

Let me temper those with saying, so far, I do like the new version. Three major items have been missing from my iPhone life (since I also use a Blackberry with work).

1. Searching email (I do this regularly)
2. Reading email in landscape (I receive far too many html emails that I can’t easily read on the iPhone)
3. Cut/Copy/Paste (Everyone’s been waiting for this one. That was my original surprise and complaint on the very 1st version of the iPhone software and it’s been a long wait)

All of these were solved with version 3.0, thankfully.

I’m still wondering just how many undos I can actually do on the device. I’ve tested it up to 3 times and got bored.

Bugs:

The bugs (and one complaint) I’ve seen so far:

1. Syncing Notes: First, it took me and another techie co-worker a few guesses to figure out just WHERE the notes would sync. I eventually guessed right that it would try to stick it in the Notes section of the Mail.app (which sucks since we tend to use Entourage here, not that I like Entourage). Mail in turn won’ t let you even open the Application without setting up an email account. Then the original syncing wouldn’t work until my co-worker figured out that a note had to be created within the Mail.app before any syncing would occur. It must need the file where notes are stored created on the computer first even though there are items on the device beforehand. This a bug in my book.

2. iPhone wants to “Backup” constantly: I’ve synced several times in the past day and already the I’m having bad flashbacks to the switch from Version 1 to 2 of the iPhone OS. That version ALWAYS wanted to do a backup of the device which usually took an hour for a simple sync. Apple eventually fixed this with an update, but it seems to be happening again in an only lesser form. Grrrrrrr.

Complaint:

The only complaint I’ve had so far is Apple not allowing iPhone 2G to use the tethering. People have been doing this for 2 years on jailbroken phones, so I know it’s technically feasible. Can’t think of a rationale for not allowing it other than AT&T complaining that the EDGE network couldn’t handle it. Double-Grrrrrrr.