TweetFollow Us on Twitter

Uninstalling with AppleScript

Volume Number: 23 (2007)
Issue Number: 05
Column Tag: Scripting

Uninstalling with AppleScript

Building an uninstaller with AppleScript Studio

By José R.C. Cruz

Introduction

In a previous MacTech article, we learned how to use the PackageMaker tool to build a distribution package. We also learned how to localize that package for different languages, and how to customize it with scripts. But the one thing we were unable to do with the tool is to build an uninstaller.

Third-party tools such as ViseX and InstallerMaker can add an uninstall option to their installers. This feature is sadly missing from PackageMaker, though not without reason. In fact, most products are easy to remove -- they are contained in a single folder, and trashing that folder completely uninstalls the product. But some products will have multiple files installed in different directories. Others will create custom directories to store the files. A good example of such a product is Xcode. Its installer creates the custom directory Developer to contain its files. The installer also stores files in other directories such as /System/Library and /Library/Application Support. As a result, removing Xcode from the system can be a laborious process. In these situations, an uninstaller tool can be useful.

This article will demonstrate how to use AppleScript Studio to build an uninstaller. To get readers started on their own uninstallers, the Xcode project Uninstall is made available for downloading. A copy of this project can be obtained at the following URL: ftp://ftp.mactech.com/src/mactech/volume23_2007/23.05.sit.

The Receipts Bundle

After the Installer installs a software payload, it creates a copy of the package in the Receipts directory. The path to this directory is /Library/Receipts on the boot volume.

The copy of the installer package is known as a receipt bundle. Its presence indicates that a product has been installed successfully. It also tells the installer package if the latter has to do an upgrade, as opposed to an installation.

Figure 1 shows the internal structure of a typical receipt bundle. Notice that the bundle has most of the same files as an installer package. What is missing is the .paz.gz file containing the actual payload. Also missing are the two aliases to that file from the Resources subdirectory.


Figure 1. Structure of a typical receipts bundle.

There are software tools that purge the contents of the Receipts directory. This is often done to reclaim extra space, especially when the product associated with the receipt no longer exists. But removing a receipt, without removing the product, creates a new problem. Without the right receipt to guide it, an installer for a new product version may be unable to upgrade the current product correctly.

The BOM File

The BOM file is a list of all the files that comprise the software payload. It also defines the locations of each file on the target volume. This file is present in both the installer package and receipts bundle.

The BOM file format has its origins in the NeXTStep operating system. It is also a binary format and, as a result, is not directly readable. To read its contents, use the command-line tool lsbom to preprocess the BOM file.

The lsbom tool

The lsbom tool takes a BOM file as its input and renders its contents into human readable text. It then outputs the text to another file, or to stdout by default. The tool is a standard addition to the BSD subsystem of MacOS X. Its counterpart is the mkbom tool, which creates a BOM file for a given directory.

To use the lsbom tool, simply pass the path to the BOM file as its input. For example, to process the BOM file for the Sample.pkg receipt, type the following statement at the Terminal prompt.

   lsbom /Library/Receipts/Sample.pkg/Contents/Archive.bom

The tool will then parse the file and display its contents at lightning speed on the Terminal speed. To better read the output, pipe the results of the lsbom tool to the less tool.

   lsbom /Library/Receipts/Sample.pkg/Contents/Archive.bom | less

less will display the first N lines of text from lsbom. The number of lines displayed is dictated by the height of the Terminal window. To display the next N lines of text, tap on the Space bar. To display the previous N lines of text, tap on the B key while holding down the <CTRL> key.

Another way of handling the lsbom output is to save it to a file. To save the output to the file Sample.log, use the I/O redirection token '>'.

   lsbom /Library/Receipts/Sample.pkg/Contents/Archive.bom > Sample.log

Notice that, in both examples, the BOM file is always inside the Contents subdirectory of the receipt bundle. Also, the name of the BOM file is always Archive.bom. Most receipt bundles will follow the same conventions. Though it is possible for a BOM file to be located elsewhere in the bundle, this is rarely done.

The lsbom output

Listing 1 shows a sample output from the lsbom tool. Each entry corresponds to a file or directory installed by the package. The first three items of the BOM entry are arranged as follows.

directory_path file_modes user_id/group_id.

Each item is separated from the other by a single tab character (0x09). Now, if the entry is for a regular file, it will have two more items as shown below.

   directory_path file_modes user_id/group_id number_of_bytes crc_32

If it is for a symbolic link, its last item will be the path to the original file or directory.

   directory_path file_modes user_id/group_id number_of_bytes ¬
         original_path

Finally, if the entry is for a device file, its last item will be the assigned device number.

   directory_path file_modes user_id/group_id device_number

Listing 1. Sample output of the lsbom tool

.   40755   501/80
./Sample.app   40755   501/80
./Sample.app/Contents   40755   501/80
./Sample.app/Contents/Info.plist   100644   501/80   947 ¬
      1163649540
./Sample.app/Contents/MacOS   40755   501/80
./Sample.app/Contents/MacOS/Sample   100755   501/80   51956 ¬
      3193247409
./Sample.app/Contents/PkgInfo   100644   501/80   8 ¬
742937289
./Sample.app/Contents/Resources   40755   501/80
./Sample.app/Contents/Resources/Appearance.tiff   100644   501/80   4850 ¬
1276692542
...
./Sample.app/Contents/Resources/English.lproj   40755   501/80
./Sample.app/Contents/Resources/English.lproj/Credits.rtf   100644   501/80 ¬  
3163   3602318773
./Sample.app/Contents/Resources/English.lproj/Errors.strings   100644 ¬  
501/80   2978   2815210102
...

Most BOM file listings consist mostly of directories and regular files. Device files and symbolic links are seldom found. Also, the file_modes item is essentially the three permission flags written in octal form. Each of the lower three numbers represents the permission for world, group, and owner. The upper set of numbers represent the type of item in question. They are set to 40 for a directory, 100 for a generic file.

Notice that each directory_path item starts with a dot (.) character. This character is replaced by the IFPkgRelocatedPath value set in the Info.plist file. If that value is not set, the directory path is assumed to be relative to the OS X boot volume.

Also, if the package has installed payloads in other directories, the BOM listing will show these payloads. For example, if Sample.pkg has installed two files in the /usr/bin directory, the BOM listing may show these files as follows.

   ./usr/bin            40755      0/0
   ./usr/bin/foo      100755   0/0   12606   2275820725
   ./usr/bin/fubar      100755   0/0   12606   2275820725

Notice that both user_id and group_id items are set to 0 in the above example. This means that the owner of the two files and the directory is root. Removing the two files will require authentication. Do not, however, remove any directories or subdirectories with a root owner. Doing so may remove important files, and render the entire OS X platform unusable.

The lsbom options

The lsbom tool also provides a number of output options. Use these options to display specific entries from the BOM file as follows.

To display only the directories accessed or created during installation, use the -d option.

   lsbom -d /Library/Receipts/Sample.pkg/Contents/Archive.bom

The output listing will also include bundles such as .app, .bundle, and .lproj. To display only the paths of files that were installed or updated, use the -f option.

   lsbom -f /Library/Receipts/Sample.pkg/Contents/Archive.bom

To display only the paths of each directory and file, use the --s option.

   lsbom -s /Library/Receipts/Sample.pkg/Contents/Archive.bom

The lsbom tool also has options other than the ones shown above. To view a list of options, type the command lsbom -h at the Terminal prompt. Also, to view the tool's electronic manual, type info lsbom at the prompt.

AppleScript and the Shell

AppleScript is the native scripting language of the MacOS platform. First introduced in the 1990s, it is one of the first few languages that work in a GUI environment. It also uses a natural language syntax, which makes its scripts easy to read and write.

Another feature of AppleScript is that it can be extended using plug-ins. These plug-ins, or scripting additions, allow AppleScript to do tasks that are slow or impossible to do using the core language. The OS X version of AppleScript comes bundled with the plug-in named Standards Additions. With this plug-in, an AppleScript script can display simple dialogs and perform basic file I/O tasks. The script can also run Unix shell scripts using the do shell script function.

,b>The do shell script function

The do shell script function is AppleScript's gateway to the BSD subsystem of MacOS X. With this function, an AppleScript script can execute command-line tools or shell script files. It can also run a single-line shell script using this function. The function returns any results from the script as a string.

The function uses the interpreter set by the SHELL environment variable to do its tasks. To find out the current interpreter, launch the Script Editor tool, which is located in /Applications/AppleScripts. On the script window, type do shell script "printenv SHELL" and click on the Run button. If the current interpreter is bash, the function will return the string value of SHELL=/bin/bash on the Results pane.

Working with file paths

When using the do shell script function to manipulate files, it requires the file paths expressed using the POSIX format. In short, a forward slash character </> must separate each path name. For example, to parse the BOM file for Sample.pkg, pass the script to the function as follows.

   do shell script ¬
      "lsbom /Library/Receipts/Sample.pkg/Contents/Archive.bom"

Now if a path name contains any spaces, a reverse slash <\> character must precede each space. For example, to parse the BOM file for Test Sample.pkg, pass the script as follows.

   do shell script ¬
      "lsbom /Library/Receipts/Test\\ Sample.pkg/Contents/Archive.bom"

Notice that two reverse slashes precede the space in Test Sample.pkg. This is necessary due to a little quirk in AppleScript. The first reverse slash tells AppleScript to treat the second slash is part of the string. The second slash tells the shell interpreter to treat the space as part of the script text.

AppleScript, however, expresses its file paths using the MacOS format. Instead of a forward slash, each path name is separated by a colon <:> character. Also, each path name can contain spaces without the need for any reverse slashes. For example, the file path to the BOM file for Test Sample.pkg is written in MacOS format as follows.

   OS X:Library:Receipts:Test Sample.pkg:Contents:Archive.bom

Converting between file path formats can be quite tedious. To address this issue, the Standards Additions plug-in provides the POSIX file class. To convert the MacOS file path to Sample.pkg to the POSIX format, type the following statement in the Script Editor window.

   POSIX path of alias "OS X:Library:Receipts:Sample.pkg"

This will return the converted path as /Library/Receipts/Sample.pkg. To convert it back to a MacOS format, type the following on the editor window.

   POSIX file "/Library/Receipts/Sample.pkg"

Both examples have file paths set relative to the boot volume. Both also assume that the MacOS name of the boot volume is OS X. Now if a file path is set relative to a volume other than boot, the conversion will reflect that volume. For example, if the MacOS file path is set to Users:Applications:Public:, it will be /Volumes/Users/Applications/Public/ in POSIX format.

Authenticating a command

Some shell commands require authentication in order to perform their tasks. They are usually invoked in the Terminal window using the sudo command. For example, to create the subdirectory foo in /usr, type the following line at the Terminal prompt.

   sudo mkdir /usr/foo

The sudo command first prompts the user for an administrative password. When the correct password is entered, sudo then executes the mkdir command. Otherwise, it aborts after the user fails to enter the right password thrice in a row.

Using the sudo command through the do shell script function is both tedious and unnecessary. Instead, the function can authenticate the desired command by itself. For example, to create the same subdirectory shown above, type the following line on the Script Editor window.

   do shell script "mkdir /usr/foo" with administrator privileges

The function first prompts the user for a password using the dialog shown in Figure 2. Again, when the user enters the correct username and password, the function then executes the mkdir command. Otherwise, it aborts with an error message after the user fails to enter the right information three times in a row. The same also happens if the user clicks on the Cancel button.


Figure 2. The authentication dialog.

To use either approach, make sure that you have a user account with administrative privileges. To learn how to create such an account, consult one of the references listed at the end of this article.

Building with AppleScript Studio

There are many ways to build an uninstaller. One way is to build it as a shell script. One example is Xcode, which comes with a Perl script to uninstall its various components. This approach is easy to implement and test. It does, however, require the use of the Terminal window. It also provides very poor user interaction and feedback, if any.

Another way is to build the uninstaller as a Cocoa application. Cocoa gives the uninstaller a better way of interacting with the user. It also allows the uninstaller to perform tasks not possible with a shell command. But this approach requires too much resources and time to implement. It also has a very high learning curve.

A more practical way is to build the uninstaller as an AppleScript application. This is now easy to do with AppleScript Studio. The uninstaller gets a decent interface with which to interact with the user. It will be easy to build and test due to AppleScript's user-friendly syntax. This is the approach used for the Xcode project Uninstall.

Laying out the user interface

The Uninstall project has a single main window named Uninstall Demo. The window is subdivided into two panels by an NSTabView control. Both panels contain a single NSTableView control. The first table displays the contents of the Receipts directory (Figure 3). The second table displays the contents of the BOM file for the selected receipt (Figure 4).


Figure 3. The Uninstall window, Receipts panel.


Figure 4. The Uninstall window, Files panel.

The entire window layout is that of a basic Assistant. On the lower right corner are two pushbuttons, Prev and Next. The Next button is also set as the default button.

Both buttons are disabled by default. The Next button is enabled when the Receipts table has a selected entry. The Prev button is enabled when the current panel is the one with the Files table. Also, when the Files table has a selected entry, the Next button becomes the Uninstall button.

On the lower left corner of the window is the Cancel button. This button is set to respond to the <Esc> key. It also sends a performClose: message to the window when clicked.

Binding the widgets

The window and some of the controls are then bound to specific AppleScript handlers. The bindings are set in the AppleScript panel of the Show Inspector dialog (Figure 5). To display the dialog, choose Show Inspector from the Tools menu. Then select AppleScript from the drop-down list at the top of the dialog.


Figure 5. The Show Inspector dialog, AppleScript panel.

Table 1 is a list of the bindings set for each interface widget. The handlers shown in this table are all defined in the source file Uninstall.applescript. Notice that some widgets are bound to the same handlers. To identify which widget called the handler, check its name property. For instance, the following code fragment shows how to determine which button was clicked.

on clicked theObject
   local tBtn
   
   set tBtn to the (name of theObject) as string
   if (tBtn is equal to "prev") then
      -- the Previous button has been clicked
   else if (tBtn is equal to "next") then
      -- the Next button has been clicked
   end if -- (tBtn is equal to "prev")
end clicked -- theObject

Widget Name Class AppleScript Settings
Name Event Handler
Uninstall Demo NSWindow demo Nib awake from nib
Prev NSButton prev Action clicked
Next NSButton image/next Action clicked
Receipts NSTableView rcpt Nib awake from nib
Data View selection changed
Lists NSTableView list Nib awake from nib
Data View selection changed

Table 1. AppleScript settings for the Uninstall UI widgets.

Not shown in the table are the bindings for the application itself. To bind the application, select the File's Owner icon on the MainMenu.nib window. Then, from the Show Inspector dialog, click on the Application checkbox. Then set the bindings as shown in Figure 6.


Figure 6. Binding the AppleScript application.

Binding the Cancel button

On the other hand, the Cancel button is not bound to any AppleScript handler. Instead, it is bound directly to an action handler.

To set the binding, control-drag a line from the button to the main window. This will display the Show Inspector dialog with the Connections panel view active. Click on the Target/Action tab on the dialog. Then choose performClose: from the list of window actions (Figure 7).


Figure 7. Selecting the performClose: action.

The Quit Uninstall menu item is also bound in the same way. But this will be left as an exercise to the readers.

Building with Xcode

The Xcode project Uninstall contains three AppleScript source files. The Uninstall.applescript file has all the handlers called by the UI widgets. The Receipts.applescript file has the code to access the Receipts directory. Finally, the Files.applescript file has the code for processing the BOM file. It also has the code that will do the uninstall task.

For reasons of length, this article will only show code that is relevant and interesting. Readers can always view the entire source files by downloading the project from the MacTech website.

Accessing the Receipts directory

Shown in Listing 2 is the function handler that retrieves the contents of the Receipts directory. It takes a path to the directory as its input argument. It returns the results of the retrieval as a list of records.

First, the handler calls the list folder function to read the directory contents. The function responds by returning the contents as a list of filenames. Next, the handler parses each filename in the list. If the name belongs to a receipt bundle, the handler retrieves its bundle signature. Otherwise, the handler proceeds to the next name.

The handler uses the bundle signature to create a record together with the name. When done, it appends the record to the return list tPkg.

Listing 2. Retrieving a list of receipt bundles (Receipts.applescript).

property pRcptRec : {bnom:"", bsig:""}
to getBundles from aPath
   local tLst, tPkgs
   local tItem, tNom
   local isPkg
   
   -- read the contents of the directory
   set tLst to (list folder aPath)
   
   -- parse the list results
   set tPkgs to {}
   copy pRcptRec to tRec
   
   repeat with tNom in tLst
      -- prepare a path to a list item
      set tItem to aPath & ":" & tNom
      get info for file tItem
      
      -- is the item a bundle?
      set isPkg to package folder of result
      
      if (isPkg) then
         -- retrieve the bundle signature
         set tSig to (getBundleSignature for tItem)
         
         -- update the record template
         set bnom of tRec to tNom
         set bsig of tRec to tSig
         
         -- add the updated record to the list
         copy tRec to the end of tPkgs
      end if -- (isPkg)
   end repeat -- with tNom in tLst
   
   -- return the retrieval results
   return (tPkgs)
end getBundles -- from aPath

Reading the BOM file

Listing 3 shows the function handler used to convert the BOM file. It also shows how to use the do shell script function to call the lsbom tool. The handler takes a path to the receipt bundle as its input argument. If successful, it returns the file path to a temp file; otherwise, it returns an empty string.

First, the handler gets a path to the TemporaryItems directory. It converts the path to a POSIX formant, and appends the name of the temp file bom.out. This file will store the output results of the lsbom tool.

The handler then prepares the script to be executed with the do shell script function. The script consists of the file path to the BOM file, as well as the path to bom.out. For example, if the target receipt is Sample.pkg, the script will read as follows.

   lsbom --p fs /Library/Receipts/Sample.pkg/Contents/Archive.bom ¬ 
               > ~/Library/TemporaryFiles/bom.out

Note that, in actual practice, the entire script will consists only of a single line. It will also state the full path to the bom.out file on the user home directory.

Notice as well that a --p fs option is passed to the lsbom tool. This option tells the tool to display only the file paths and sizes of each BOM item. If the item happens to be a directory, its entry in the bom.out file will not have any size data.

Listing 3. Generating a BOM file for a given receipt (Files.applescript).

property pBOMPath : "/Contents/Archive.bom"
property pBOMTemp : "bom.out"
property pCmd : "lsbom "
property pOpts : "-p fs "
to getBOM for aRcpt
   local tTmp, tCmd
   
   -- retrieve a path to a temp directory
   set tTmp to path to temporary items from user domain
   set tTmp to POSIX path of tTmp
   
   -- prepare the output file path
   set tTmp to tTmp & "/" & pBOMTemp
   
   -- prepare the shell command
   set tCmd to pCmd & pOpts
   set tCmd to tCmd & aRcpt & pBOMPath
   set tCmd to tCmd & " > " & tTmp
   
   -- execute the shell command
   do shell script tCmd
   
   -- was it successful?
   try
      set tTmp to (POSIX file tTmp) as string
      alias tTmp
      return (tTmp)
   on error tErr number tTyp
      display dialog ("[FATAL]" & tErr as string)
      return ("")
   end try
end getBOM -- for aRcpt

Listing 4 shows the function handler used to parse the contents of the bom.out file. It takes the path to that file as its input argument. When done, it returns a list of records, each record representing a BOM entry.

The handler first opens a read-only access to the bom.out file. It reads all the entries in the file, and then closes the access.

The entries consist of a list of strings. Each entry alternates between the file path and size of a BOM item. The handler creates a BOM record for each entry. It then appends the record to the list variable tBOM, which is returned to the calling handler.

Listing 4. Reading the BOM file (Files.applescript).

property pBOMRec : {fnom:"", fsiz:""}
property pLF : 10
property pHT : 9
to loadBOMItems from theFile
   local tSrc, tSiz, tPos, tLen
   local tLst, tBOM, tDat, tRec, tNom
   local tTkn, tOdd
   
   -- initialize the following locals
   set tBOM to {}
   set tTkn to {}
   set tTkn to tTkn & (ASCII character pLF)
   set tTkn to tTkn & (ASCII character pHT)
   
   try
      -- start a read-only access to the file
      open for access theFile without write permission
      set tSrc to result
      if (tSrc > 0) then
         -- read the contents of the file
         read tSrc using delimiter tTkn
         set tLst to result
         
         -- close the read-only access to the file
         close access tSrc
      end if -- (tSrc > 0)
      
      -- parse the BOM entries
      copy pBOMRec to tRec
      set tLen to the length of tLst
      
      if (tLen > 0) then
         repeat with tPos from 1 to tLen by 2
            -- retrieve the following BOM items
            set tNom to item tPos of tLst
            set tSiz to item (tPos + 1) of tLst
            if (tSiz is equal to "") then
               set tSiz to "-1"
            end if -- (tSiz is equal to "")
            
            -- prepare the BOM record
            set fnom of tRec to (tNom as string)
            set fsiz of tRec to (tSiz as string)
            
            -- append the record to the return list
            copy tRec to the end of tBOM
         end repeat -- with tPos from 1 to tLen by 2
         
         -- remove the first two items
         set tLen to length of tBOM
         set tBOM to items 3 thru tLen of tBOM
end if -- (tSiz > 0)
   on error tErr
      -- something wrong has happened
      display dialog ("[FATAL] loadBOMItems:" & tErr as string)
   end try
   
   -- return a list of BOM entries
   return (tBOM)
end loadBOMItems -- theFile

Removing a BOM item

There are a many ways to remove a software product. The direct way is to locate the topmost directory from the BOM, and delete it together with its contents. Another way is to select specific items from the BOM for deletion. Choosing the right approach depends on the aim of the uninstaller. The Uninstall project, for instance, uses a variant of the second approach.

Shown in Listing 5 is the function handler that will remove a BOM item. It is called after the user selected an item from the Files listbox, and clicked on the Uninstall button.

The handler first creates an Uninstall folder in the TemporaryItems directory. Next, it moves the BOM item from its original path to the folder. It also deletes the item at the specified path. Once the handler completes its task, it returns a true to the calling handler. Otherwise, it returns a false if any errors occurred.

Listing 5. Removing a BOM item (Files.applescript).

   property pDirTrash : "Uninstall"
   to removeTheItem given path:aTgt, folder:aDir
      local tTmp, tBin, tCmd
      
      -- initialize the following locals
      set tTmp to path to temporary items from user domain as string
      set tBin to tTmp & pDirTrash
      
      -- create the temporary uninstall directory
      tell application "Finder"
         try
            if not (exists alias tBin) then
               make new folder at folder tTmp ¬
                  with properties {name:"Uninstall"}
            end if -- (exists alias tBin)
         on error tErr
            display dialog ¬
               "[FATAL] Failed to create the Uninstall directory"
            return false
         end try
      end tell -- application "Finder"
      
      -- attempt to remove the item
      tell application "Finder"
         try
            -- is the item a directory or a file?
            if (aDir) then -- it is a directory
               -- test delete the directory
               move folder aTgt to folder tBin with replacing
               delete folder aTgt
            else -- it is a file
               -- test delete the file
               move file aTgt to folder tBin with replacing
               delete file aTgt
            end if -- (aDir)
         on error tErr
            display dialog "[ERROR] " & tErr
            return false
         end try
      end tell -- application "Finder"
      
      -- the removal was successful
      return (true)
   end removeTheItem -- given path:aTgt, type:aTyp

Notice that the handler uses the Finder to delete the BOM item. While this works in most cases, it will fail if the item is inside a restricted directory such as /usr. For that case, replace the delete code with the following script statements.

   set aTgt to the POSIX path of alias aTgt
   set tCmd to "rm -Rf " & aTgt
   do shell script tCmd with administrator privileges

The above statements will prompt the user to validate the deletion that is about to occur.

Also, notice that the handler first makes a copy of the BOM item it is about to delete. This gives the user a chance to restore the deleted item back to its former location.

Final Thoughts

Product removal is just as important as product installation. Though most products are easy to remove manually, some require the use of an uninstaller tool. The tool will peruse the receipt package for the product, and delete all the files that belong to that product. This will help ensure that future products installations will be more successful.

AppleScript Studio makes it quite easy to build an uninstaller tool. It has a much lower learning curve compared to Cocoa. This alone makes for a faster build and deployment cycle. It allows the addition of a user-friendly interface, which is not possible through shell scripts.

Hopefully, this article helps to get you started in writing your own uninstaller. Until Apple adds an uninstall option to the Installer tool, writing your own is, for now, the next best solution.

Bibliography and References

Apple Computers. AppleScript Resources. Retrieved 2007 Feb 24. Online: http://www.apple.com/applescript/resources.

Apple Computers. "do shell script in AppleScript". Technical Note TN2065. Copyright 2003, 2005, 2006. Apple Computers, Inc.

Apple Computers. "Administrative Accounts". An Introduction to MacOS X Security for Web Developers. Copyright 2007. Apple Computers, Inc. 2004 Aug 25. Online: http://developer.apple.com/internet/security/securityintro.html

Apple Computers. "lsbom -- list contents of a bom file". Mac OS X Man Pages. Copyright 2003. Apple Computers, Inc. 2003 Apr 16. Online: http://developer.apple.com/documentation/Darwin/Reference/Manpages/man8/lsbom.8.html.


JC is a freelance engineering consultant and writer currently residing in North Vancouver, British Columbia. He divides his time between writing technical articles, and teaching origami at his local district's public library. He can be reached at anarakisware@cashette.com.

 
AAPL
$111.78
Apple Inc.
-0.87
MSFT
$47.66
Microsoft Corpora
+0.14
GOOG
$516.35
Google Inc.
+5.25

MacTech Search:
Community Search:

Software Updates via MacUpdate

NeoOffice 2014.6 - Mac-tailored, OpenOff...
NeoOffice is a complete office suite for OS X. With NeoOffice, users can view, edit, and save OpenOffice documents, PDF files, and most Microsoft Word, Excel, and PowerPoint documents. NeoOffice 3.x... Read more
LibreOffice 4.3.5.2 - Free Open Source o...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
CleanApp 5.0.0 Beta 5 - Application dein...
CleanApp is an application deinstaller and archiver.... Your hard drive gets fuller day by day, but do you know why? CleanApp 5 provides you with insights how to reclaim disk space. There are... Read more
Monolingual 1.6.2 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
NetShade 6.1 - Browse privately using an...
NetShade is an Internet security tool that conceals your IP address on the web. NetShade routes your Web connection through either a public anonymous proxy server, or one of NetShade's own dedicated... Read more
calibre 2.13 - Complete e-library manage...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Mellel 3.3.7 - Powerful word processor w...
Mellel is the leading word processor for OS X and has been widely considered the industry standard since its inception. Mellel focuses on writers and scholars for technical writing and multilingual... Read more
ScreenFlow 5.0.1 - Create screen recordi...
Save 10% with the exclusive MacUpdate coupon code: AFMacUpdate10 Buy now! ScreenFlow is powerful, easy-to-use screencasting software for the Mac. With ScreenFlow you can record the contents of your... Read more
Simon 4.0 - Monitor changes and crashes...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
BBEdit 11.0.2 - Powerful text and HTML e...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more

Latest Forum Discussions

See All

Make your own Tribez Figures (and More)...
Make your own Tribez Figures (and More) with Toyze Posted by Jessica Fisher on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
So Many Holiday iOS Sales Oh My Goodness...
The holiday season is in full-swing, which means a whole lot of iOS apps and games are going on sale. A bunch already have, in fact. Naturally this means we’re putting together a hand-picked list of the best discounts and sales we can find in order... | Read more »
It’s Bird vs. Bird in the New PvP Mode f...
It’s Bird vs. Bird in the New PvP Mode for Angry Birds Epic Posted by Jessica Fisher on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Telltale Games and Mojang Announce Minec...
Telltale Games and Mojang Announce Minecraft: Story Mode – A Telltale Games Series Posted by Jessica Fisher on December 19th, 2014 [ permalink ] | Read more »
WarChest and Splash Damage Annouce Their...
WarChest and Splash Damage Annouce Their New Game: Tempo Posted by Jessica Fisher on December 19th, 2014 [ permalink ] WarChest Ltd and Splash Damage Ltd are teaming up again to work | Read more »
BulkyPix Celebrates its 6th Anniversary...
BulkyPix Celebrates its 6th Anniversary with a Bunch of Free Games Posted by Jessica Fisher on December 19th, 2014 [ permalink ] BulkyPix has | Read more »
Indulge in Japanese cuisine in Cooking F...
Indulge in Japanese cuisine in Cooking Fever’s new sushi-themed update Posted by Simon Reed on December 19th, 2014 [ permalink ] Lithuanian developer Nordcurrent has yet again updated its restaurant simulat | Read more »
Badland Daydream Level Pack Arrives to C...
Badland Daydream Level Pack Arrives to Celebrate 20 Million Downloads Posted by Ellis Spice on December 19th, 2014 [ permalink ] | Read more »
Far Cry 4, Assassin’s Creed Unity, Desti...
Far Cry 4, Assassin’s Creed Unity, Destiny, and Beyond – AppSpy Takes a Look at AAA Companion Apps Posted by Rob Rich on December 19th, 2014 [ permalink ] These day | Read more »
A Bunch of Halfbrick Games Are Going Fre...
A Bunch of Halfbrick Games Are Going Free for the Holidays Posted by Ellis Spice on December 19th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »

Price Scanner via MacPrices.net

13-inch 2.6GHz Retina MacBook Pro on sale for...
Best Buy has lowered their price on the 2014 13″ 2.6GHz/128GB Retina MacBook Pro to $1149.99 on their online store for a limited time. That’s $150 off MSRP and the lowest price available for this... Read more
Kodak Returns to CES With New Consumer Produ...
Former photography colossus Kodak is returning to CES for the first time in three years where the Kodak booth (#21818 South Hall 1) will showcase a wide range of innovative, imaging-related products... Read more
Invaluable Launches New Eponymously -Named A...
Invaluable, the world’s largest online live auction marketplace, hhas announced the official launch of the Invaluable app for iPad, now available for download in the iTunes App Store. Invaluable... Read more
IDC Reveals Worldwide Mobile Enterprise Appli...
International Data Corporation (IDC) last week hosted the IDC FutureScape: Worldwide Mobile Enterprise Applications and Solutions 2015 Predictions Web conference. The session provided organizations... Read more
Hello Vino Wine App Launches “Safe Ride Home”...
Hello Vino has announced addition of a new “Get a Safe Ride Home” feature in its Food & Drink app with a direct connection to Uber, the technology platform that connects users with rides. The... Read more
DEVON-technologies Releases DEVONthink To Go...
Coeur d’Alene, Idaho based DEVON-technologies, LLC has updated DEVONthink To Go, its mobile companion to DEVONthink, to version 1.5. The update includes an iOS 8 extension, compatibility with the... Read more
The Apple Store offering free next-day shippi...
The Apple Store is now offering free next-day shipping on all in stock items if ordered before 12/23/14 at 10:00am PT. Local store pickup is also available within an hour of ordering for any in stock... Read more
It’s 1992 Again At Sony Pictures, Except For...
Techcrunch’s John Biggs interviewed a Sony Pictures Entertainment (SPE) employee, who quite understandably wished to remain anonymous, regarding post-hack conditions in SPE’s L.A office, explaining “... Read more
OtterBox Defender Series Case For iPad mini 3...
With their innovative Touch ID technology and ultrathin profile, the latest tranche of Apple iPads are more desirable than ever, and OtterBox has just announced the Defender Series custom-engineered... Read more
Holiday sales this weekend: MacBook Pros for...
 B&H Photo has new MacBook Pros on sale for up to $300 off MSRP as part of their Holiday pricing. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $1699... Read more

Jobs Board

*Apple* Store Leader Program (US) - Apple, I...
…Summary Learn and grow as you explore the art of leadership at the Apple Store. You'll master our retail business inside and out through training, hands-on experience, Read more
Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.