Here’s another update of my checklibs script for analyzing dynamic library dependencies of Mach-O binaries. See earlier articles for an introduction.
It’s in fact not an update but a complete rewrite that was needed to handle the complex load path relationships that can be expressed with some of dyld’s newer features such as @rpath. The script should be able to properly display every possible linking combination. If it doesn’t, let me know so I can try to make it smarter.
The main use case is still to catch the unintentional linking against nonstandard frameworks and libraries. Here’s how to use it:
checklibs.py /path/to/Foo.app/Contents/MacOS/Foo
There are some command line options, use the --help option to get a list of them.
Referenced non-embedded frameworks in nonstandard locations are highlighted in blue. Frameworks that are not found on the file system are marked with a red (missing).

If a framework is embedded and referenced with one of the @ placeholders @executable_path, @loader_path or @rpath, the script shows both the original and the resolved path so you can see how a particular binary was found.
In the case of @rpath, the script also shows which binary supplied the rpath value that was used.
The new version, called checklibs.py, is on github. Feel free to enhance it and send pull requests.
I recently wanted to watch the thread count history of a running application as a graph in Instruments. I didn’t find a built-in instrument that showed me exactly what I needed, so I configured a custom instrument.
Custom instruments are based on dtrace probes. When I set up a custom instrument, I usually write a pure dtrace script first, independent of Instruments. It’s easier to tweak it until I get it exactly right, and it’s useful to have a command line variant anyway. When that works, I copy/paste the relevant parts into the instrument configuration sheet.
The main task was figuring out which providers and probes to use. A DTrace documentation search for various combinations containing “thread” didn’t turn up anything useful. I later realized and remembered that the Solaris/DTrace terminology for thread is light weight process, and indeed there are lwp-create and lwp-exit probes in the proc provider that fire at the appropriate times. What helped me find these probe names were the Darwin kernel sources. The locations that set up threads are instrumented accordingly (look for lwp__create and lwp__exit).
The curpsinfo->pr_nlwp value provides the number of threads. Putting everything together results in this script (which is on github):
BEGIN
{
globalIndex = 0;
}
proc:::lwp-start
/pid == $target/
{
this->mIndex = ++globalIndex;
printf("[%d] thread start, count = %d", this->mIndex, curpsinfo->pr_nlwp);
}
proc:::lwp-exit
/pid == $target/
{
this->mIndex = ++globalIndex;
printf("[%d] thread exit, count = %d", this->mIndex, curpsinfo->pr_nlwp);
}
Run it like this, replacing 1234 with your target process id:
sudo dtrace -s thread-count.d -p 1234
The output looks like this:
thread_info_internal:lwp-create 1287183987 [710] thread create, count = 34 thread_info_internal:lwp-create 1287183987 [713] thread create, count = 35 thread_terminate_self:lwp-exit 1287183987 [715] thread exit, count = 34 thread_info_internal:lwp-create 1287183989 [716] thread create, count = 34 thread_info_internal:lwp-create 1287183989 [717] thread create, count = 35 ...
The configuration in Instruments:

The options provided by the instrument inspector define what gets plotted:


And finally the result:

Out of the box git diff doesn’t display a readable diff for Cocoa .strings files because it sees the UTF-16 encoded text files as binary files:
Binary files a/Localizable.strings and b/Localizable.strings differ
Not very useful. With two small configuration changes you can get a readable diff:
First, add this to the project’s .git/info/attributes file:
*.strings diff=localizablestrings
(Unfortunately you do have to add it to every project, there doesn’t seem to be a global attributes configuration file)
Second, add this to your ~/.gitconfig file:
[diff "localizablestrings"] textconv = "iconv -f utf-16 -t utf-8"
Now git diff shows nice readable diffs:

I put a bunch of Xcode text macros I use for writing Objective-C on GitHub, together with a cheat sheet generator:
http://github.com/liyanage/xcode-text-macros
You’re welcome to contribute additional macros to the collection.
Apple Generic Versioning (AGV) is a system that helps with software project version number management in Xcode projects. Adopting it has some benefits such as stamping the version information into the binaries in a way compatible with the what tool.
I thought about using it for my personal projects in the past, but was never comfortable with the agvtool utility manipulating files such as the Xcode project file directly. I thought that I would corrupt these files when I forgot to close the project in Xcode before bumping a version.
I’m now much more comfortable with that thought because I realized how well Xcode handles external changes to its open files. I realized that when I moved my projects to Git and started using local branches. At first I avoided switching between those branches while the project was open in Xcode for the same reason, but when I actually tested what happens when I switch back and forth I saw that Xcode handles it well:

Obviously you shouldn’t do this with files that have unsaved changes. Xcode seems to store all changes to the project settings to its project file right away, so you usually only have to check for unsaved source code files.
Now that I’m confident that I can’t get myself into trouble with agvtool (at least not this particular kind of trouble) here’s how I set it up:
First I enable AGV on the project level. There are two settings, setting the versioning system to AGV and setting the initial version number:

Make sure you set this on the project level and in “All Configurations.” There are some other settings on the target level, but Xcode should set those to sensible default values when you flip the switch to enable AGV.
Next I replace all occurrences of the project version number in the Info.plist file with a placeholder:
<key>CFBundleGetInfoString</key>
<string>Checksum version ${CURRENT_PROJECT_VERSION}, Copyright ...</string>
<key>CFBundleShortVersionString</key>
<string>Checksum version ${CURRENT_PROJECT_VERSION}</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
From now on I can bump versions on the command line like this:
agvtool new-version 2.9
Xcode will display its “changed externally” message when it’s coming to the front again and after it reloads the project you can build with the new version number.
These two articles cover Xcode project versioning in much more detail, including alternatives to AGV:
http://www.dribin.org/dave/blog/archives/2006/08/02/versioning_os_x_apps/
http://chanson.livejournal.com/125568.html
Ted Stresen-Reuter, author of a big, popular BBEdit clipping set for PHP, Carlton Gibson, and I recently combined all our BBEdit clipping sets into one big collection, and the result is now on GitHub:
http://github.com/tedmasterweb/bbeditclippings/
This was a good opportunity to clean up the sets, especially the one for Perl. It got lots of new clippings and a more modern coding style in existing clippings.
I also realized that the sets on my site were always hopelessly out of date because I never published new versions when I improved and added clippings. With the code now available on GitHub, publishing is much easier for me and users of the sets can always update to the most recent version with a quick git pull.
You’re welcome to contribute additional clipping sets for other programming languages to this collection. If want to add your set, use GitHub’s fork feature to clone our project, then add your stuff and let us know about it.
Here’s an updated version of checklibs.pl, a developer tool that lists dynamic library dependencies of Mac OS X binaries. I introduced it in an earlier article.
The new version colorizes all libraries that are outside of the /System and /usr/lib directories and therefore not part of a standard Mac OS X installation.
The color helps spotting non-standard libraries. For each one, you have to determine if the dependency is a build mistake (hello MacPorts or Fink in $PATH) or if it’s OK because the library will be shipped and installed along with the binary.
The script is now under revision control as part of my Mac OS X shell script collection on GitHub:
http://github.com/liyanage/macosx-shell-scripts
I got a notice from Amazon telling me to change my Album Artwork Assistant application within 60 days so that it signs its search requests to the Amazon AWS product information web service. I use this service to find album artwork images.
Amazon provides some notes and examples for Java, Perl and C#, but not for Objective-C. I wrapped my signed request URL generation in a class that other Cocoa developers can reuse. It’s available here:
SignedAwsSearchRequest.h and SignedAwsSearchRequest.m
Example usage can be seen in the unit test file TestSignedAwsSearchRequest.m
I have written about clearing Apple’s Internet download quarantine flag from files to get rid of the security warning before.
Recently Apple pushed Xcode documentation updates frequently, and I somtimes had to clear the flag from other HTML files all over the harddisk, not just in /Developer. The old way was just too slow for frequently changing and/or big sets of files:
find /Developer -type f -name '*.html' \
-exec sh -c 'xattr "$0" | grep -q quarantine && xattr -d com.apple.quarantine "$0"' {} \; -print
This spawns lots of subprocesses and it turns out that xattr is not a native binary but a Python script, which means that the Python interpreter is fired up twice for each file.
It takes ages this way so I rewrote it to loop in Python and use Python’s native xattr module:
#!/bin/bash
#
# Remove the quarantine extended attribute from all
# developer documentation HTML files to get rid
# of the "downloaded from the Internet" warning
#
# Marc Liyanage / www.entropy.ch
#
[ $UID -eq 0 ] || { echo $0 must be run as root; exit 1; }
find /Developer -type f -name '*.html' | python <(cat - <<EOF
#!/usr/bin/env python
from xattr import *
import sys
import string
attr = 'com.apple.quarantine'
for file in sys.stdin:
file = string.rstrip(file, "\n")
if (attr in listxattr(file)):
removexattr(file, attr)
EOF
)
This is a lot faster.
Here’s my take on displaying Git and SVN status information in the Bash prompt:
# Prompt setup, with SCM status
parse_git_branch() {
local DIRTY STATUS
STATUS=$(git status 2>/dev/null)
[ $? -eq 128 -o $? -eq 127 ] && return
[[ "$STATUS" == *'working directory clean'* ]] || DIRTY=' *'
echo "($(git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* //')$DIRTY)"
}
parse_svn_revision() {
local DIRTY REV=$(svn info 2>/dev/null | grep Revision | sed -e 's/Revision: //')
[ "$REV" ] || return
[ "$(svn st)" ] && DIRTY=' *'
echo "(r$REV$DIRTY)"
}
PS1='\u@\h:\W$(parse_git_branch)$(parse_svn_revision) \$ '
Put this into your ~/.bashrc script and you should see the Git/SVN status in your prompt if your working directory is a sandbox.
For SVN, it displays the current revision:
liyanage@primavera:foobar(r9851 *) $
For Git, it displays the current branch:
liyanage@primavera:build-entropy-php(php-53 *) $
For both, a * means that there are local changes to the working directory
An alternative version of parse_svn_revision(), based on David’s comment below:
parse_svn_revision() {
local REV=$(svnversion 2>/dev/null)
[ $? -eq 0 ] || return
[ "$REV" == 'exported' ] && return
echo "($REV)"
}
With that, the prompt looks like this:
liyanage@primavera:foobar(10027:10028M) $
This version is faster on large SVN trees. The original one above sometimes introduces a noticeable delay before the prompt appears.
If you’re a Perl developer on Mac OS X Leopard, then you’ve probably heard about this issue caused by Security Update 2009-001:
...the latest Mac OS X Security Update 2009-001 apparently breaks your Perl, if you
- are using Mac OS X 10.5 (Leopard)
- and are using Perl that comes with Mac OS X
- and have upgraded several core modules with CPAN in the past
I read about it a while ago but when I tried it on my machine at the time, I didn’t see the symptoms described in the article, even though I use CPAN a lot, so I thought that my system wasn’t affected.
Today, however, I had to track down a strange, hard to find bug where I would get messages like this:
Modification of a read-only value attempted
At first I thought I made some Perl beginner mistake, but in the end it turned out that I did indeed have a broken List::Util module with a version mismatch between the XS binary and the Perl module code. After downloading, compiling and installing a fresh copy of Scalar-List-Utils from CPAN, everything was back to normal.
Putting it here in the hope that it saves some other googling Perl developer some time :-)
I converted my personal Subversion repository to Git and collected a few notes.
My repository contains the source code of my Mac OS X projects, but also a lot of one-off test programs and experiments. It is a very basic repository; there are no branches at all (maybe I'll use them more with Git) and very few of my projects used tags, so the conversion was straightforward. Because there was so little information to preserve, this is not representative of an SVN -> Git conversion in general, but the notes might still be useful for other people converting their personal repos.
I had about 50 projects in Subversion, some big and some with just one or two files. Each project was in its own subdirectory below the repository root. They were unrelated, so I wanted to separate the projects into their own Git repositories during the conversion.
Converting Projects With Tags
I converted each of the few projects that did use tags manually, like this:
SVN_BASE=svn+ssh://host/path/to/svnroot PROJECT=album-artwork-assistant git svn clone --trunk="$SVN_BASE/trunk/$PROJECT" --tags="$SVN_BASE/tags/$PROJECT/versions" "$SVN_BASE/trunk/$PROJECT" cd $PROJECTTo convert the SVN tags to real Git tags I ran a modified version of a script by Frank S. Thomas:
#!/bin/bash
GIT=/opt/local/bin/git
for branch in $($GIT branch -r); do
if [ $(echo $branch | egrep "tags/.+$") ]; then
version=v$(basename $branch)
subject=$($GIT log -1 --pretty=format:"%s" $branch)
export GIT_COMMITTER_DATE=$($GIT log -1 --pretty=format:"%ci" $branch)
echo "Tag $version [Y/n]?"
read yesno
if [ -z $yesno ] || [ $yesno = "Y" ]; then
$GIT tag -a -f -m "$subject" "$version" "$branch^"
$GIT branch -d -r $branch
fi
fi
done
This next step converts svn:ignore properties to .gitignore files
git svn create-ignore git commit -m 'added .gitignore converted from svn:ignore' cd ..
All of this gave me a working copy repository in $PROJECT. I converted it to a bare repository like this:
git clone --bare $PROJECT
The bare repo was now in $PROJECT.git
Converting Simple Projects Without Tags
For all the other simple projects without any tags I used this script:
#!/bin/bash WD="$PWD" GIT="/opt/local/bin/git" SVN_TRUNK=svn+ssh://host/path/to/svnroot/trunk PROJECTS=$(svn list "$SVN_TRUNK" | sed -e 's#/$##') [ -d logs ] || mkdir logs for project in $PROJECTS; do cd "$WD" [ -d "$project.git" ] && continue LOG="$WD/logs/$project.log" echo "\nconverting $project\n" $GIT svn clone "$SVN_TRUNK/$project" > "$LOG" cd "$project" $GIT svn create-ignore >> "$LOG" $GIT commit -m 'added .gitignore converted from svn:ignore' >> "$LOG" cd .. $GIT clone --bare "$project" "$project.git" >> "$LOG" rm -rf "./$project" done
Move to Server and Checkout Local Repositories
Together with the manually converted ones, this resulted in about 50 bare Git repositories, one per project. I moved them all to a server into a common project root directory and then cloned them back to my computer as local working copies:
for project in $(ssh myserver ls /path/to/git/projectroot); do
git clone -v ssh://myserver/path/to/git/projectroot/$i
done
Setting up gitweb
I got Git for Mac OS X via MacPorts, both on my client and on the server. It comes with the gitweb web viewer so I activated that on my server with the following Apache configuration:
Alias /git /opt/local/share/git-core/gitweb
<Location /git>
DirectoryIndex gitweb.cgi
AddHandler cgi-script cgi
Options +ExecCGI
</Location>
I had to configure the project root directory in gitweb.cgi:
our $projectroot = "/path/to/git/projectroot";
Now it’s visible externally at http://www.entropy.ch/git/
Rewriting History
After the conversion, the old commits generated bygit svn had auto-generated committer e-mail address
and name information which differed from my Git configuration values. To clean up and unify this information in the
old commits I ran these commands in each working copy:
git filter-branch --env-filter \
"export GIT_AUTHOR_NAME='Marc Liyanage' \
GIT_AUTHOR_EMAIL='email@example.com' \
GIT_COMMITTER_NAME='Marc Liyanage' \
GIT_COMMITTER_EMAIL='email@example.com'"
git push --force
github
One nice benefit of using Git is that I get to host code on github for free. I push some of my more recent projects there from time to time.
MySQL Workbench is coming to the Mac (and Linux). This program is a great database design tool, I use its Windows version to model relational databases visually. It gives me two kinds of very useful results:
- DDL SQL files that I can send directly to the MySQL database server to initialize my database schema
- database model diagram vector images that I can use for high quality output technical documentation and also for training and discussion purposes
Here’s MySQL’s announcement of the Mac version:
http://dev.mysql.com/workbench/?p=192
As they note, it’s a very early preview that’s probably not yet ready for production, but it already looks great and opens and displays my model file from the Windows version fine.
When I say it looks great I’m really a bit surprised because I expected a really ugly port like so often with cross-plattform applications (I’m thinking of the ugliness that is often QT and I’m looking in the general direction of Google Earth when I say this).


I saw some visual glitches in other parts of the interface, for sure, but overall it’s a positive first impression.
At work I recently gave a presentation about the practical aspects of public key cryptography with the OpenSSL toolkit. This is an expanded transcript of the presentation, published here on my blog in the hope that it’s useful for a broader audience.
There are four parts covering these major topics:
- Part 1: Public Key Cryptography
- Part 2: Public Key Infrastructure (PKI)
- Part 3: Inspecting and Creating X.509 Certificates
- Part 4: OpenSSL Bag of Tricks
You are reading part 2, about Public Key Infrastructure (PKI). This part shows the practical problems with simple public key cryptography, and how a public key infrastructure attempts to solve them. While part 1 was fairly technical, this part is about real-world organizational structures and trust relationships. Part 3 will again be more technical, showing how these real-world concepts are mapped to systems and software.
Some things in this part are based on the German book “Kryptografie und Public-Key Infrastrukturen im Internet”. A revised English edition is available as “Cryptography and Public Key Infrastructure on the Internet”. Both are probably a bit dated by now, so you should look for newer books.
Practical Problems With Plain Public Key Cryptography
There are a few practical issues with the basic operations provided to us by plain public key crypto. The next few sections highlight some of them:
- Key authenticity
- Key revocation
- Key validity periods
There are other issues not discussed here, such as non-repudiation and policy enforcement.
For public cryptography to be useful in real-world use on a large scale, these issues need to be addressed, and that is what a Public Key Infrastructure, or PKI, is about.
Key authenticity
Part 1 didn’t go into the details of how two parties who want to exchange encrypted or signed messages exchange their public keys, but these details are critical.
One possibility is to exchange the keys at a face-to-face meeting. This approach is not feasible on a large scale, and public key cryptography with its asymmetric nature is interesting exactly in a large scale scenario.
In the absence of a secure communications channel for key exchange between the two parties, another possibility is to exchange the keys over an open, untrusted network like the Internet. The problem with this is that the recipient of the key can never be sure if the key is authentic.
A third party C, with the ability to intercept messages on the untrusted network, could intercept the public key in transit from the sender A to the recipient B and note it. C could generate a new key pair and send the public key to B, pretending to be A. If B then uses this public key to send an encrypted message to A, the third party could again intercept the message, decrypt it with the private key it generated to read the message, and then re-encrypt the message using A’s real public key and send it to A, pretending to be the legitimate sender B. It would work the same in the other direction and it’s called the man-in-the-middle attack (MITM).
A public key infrastructure should make it possible to verify a public key’s authenticity.
Key revocation
If a private key is compromised, we want our communication partners to stop using the related public key, otherwise confidential information is sent around and people other than the intended recipient are able to decrypt it.
A public key infrastructure should make it possible to revoke previously distributed public keys.
Key validity periods
Encryption keys should be replaced in regular intervals. One reason is that the longer a key is in use, the more material is available for cryptanalysis. Another reason is to limit the damage caused by a private key being compromised without detection.
A public key infrastructure should provide means to specify a validity period for a public key.
Trust Relationships
Ultimately, these issues are about trust and trust relationships between the involved parties. There are different types of trust relationships, and this section shows how well each one addresses the problems.
Direct Trust
This model could also be called “no infrastructure”. It’s the basic face-to-face meeting case from above, where the parties exchange their public keys directly.
It’s difficult to do with parties who are total strangers, and between difficult and impossible to do with lots of communication partners.
Key revocation means directly contacting the other party and telling them to stop using the old key.
There is no support for formal validity periods.
Web of Trust
This model is an extension of direct trust. If participants A and B have previously exchanged their keys, both can now act as introducers and sign (and forward to the other party) the public keys of all other partners they know directly. Each can add the public keys obtained this way to its list of known, trusted keys.
So if A knows B, and B knows C, B is the introducer and can:
- sign C’s public key and send it to A
- sign A’s public key and send it to C
This enables A and C each to verify the new public keys using B’s public key, which they already know and trust, and begin exchanging secure messages directly, knowing that their public keys for each other are authentic.
Now that A and C trust each other, they can again sign keys of partners they know directly, and so on, thus creating and extending the web of trust.
It is usually not just the public key that is signed, but a whole package of information that includes the public key, the subject’s name, e-mail address etc. This whole information package, when signed, is also called a certificate. Make a mental note of this, because it’s important: A certificate contains a public key and additional information, and somebody signed the whole package with a private key that’s unrelated to the public key in the package.
The party who signs the bunch of data, and therefore issues the certificate, vouches for the entire information, and not just for the public key. This means that the signing party needs to verify all information that it signs. For things like e-mail addresses, that can be through an automated process, but for things like a company or personal name, it usually requires checking official records such as commercial registry papers, passports, ID cards etc.
Handling revocation, expiration and scaling to large users bases can be difficult, as can be getting introduced into a web of trust. Wikipedia’s article on web of trust has more information.
Web of trust is the trust model used by PGP.
Hierarchical Trust
In this model, all parties agree on one or more trusted, independent authorities to issue certificates. These authorities are called certificate authorities (CAs) or trust centers.
A CA’s own certificate, which the parties need in order to verify the certificates issued by that particular CA, is called a root certificate and it is distributed widely, e.g. as part of client programs such as e-mail clients or web browsers or directly in operating systems.
Here are parts of the root certificate lists of Mac OS X and Windows XP:


Because literally millions of users trust these CA certificates, the non-disclosure of the associated private keys is absolutely critical. The CA’s organizational structures and operational processes are designed to prevent a compromise of these very important private keys. A CA has to document the quality of these structures and processes by passing an audit before its root certificate is accepted by operating system and other client software vendors. One requirement is the use of Hardware Security Modules conforming to the FIPS 140-2 standard for the generation, storage and use of the CA’s sensitive key material.
Once a party trusts a CA (by having its certificate with its public key in the list of trusted root certificates), it can immediately validate the probably very large number of certificates issued by that CA now and in the future. A CA can also sign intermediate signing keys of other CAs, and they can in turn do the same, which creates the hierarchical trust structure that gives this model its name.
With a CA in place, if two parties both trust that CA and want to communicate securely with each other using public keys certified by that CA, they both have to get a certificate. They generate a key pair and prepare a certificate request. The request is the “bunch of data” mentioned above and it consists of the public key along with all other information required by the CA, according to the CA’s policies.
These policies can vary according to the level of certification, and the price of the certificate usually depends on that level. It could be that only an e-mail address is certified and the certification is free. In other cases, commercial banking-grade certificates are issued that certify not only the name of a web site but also the organization name, after extensive review of legal proof of incorporation and domain name ownership.
After following its procedures to verify that all information presented in the certificate request is valid, the CA signs the public key and other information in the request with its private key. The result is the certificate, which is sent back to the party that requested it.
Once both parties have their certificates, they can exchange them, and they can do this even over insecure public networks because both will be able to verify the certificate’s authenticity using the CA’s root certificate, which they both already know and trust.
So how well does this trust model deal with our practical issues?
Regarding key revocation: With the centralization resulting from a limited number of trusted certificate issuers (my Mac OS X system keychain lists about 150 trusted root CAs), certificate revocation in the form of certificate revocation lists (CRLs) becomes feasible. A CRL is a list of serial numbers of certificates that the CA has revoked. When a CA issues a certificate, it includes the location of this CRL. When a client needs to verify a certificate, it can check if it is on the list of revoked certificates.
For this setup to be useful, the list needs to be updated frequently. On Mac OS X, there’s a daemon called ocspd that does just that. Its name already suggests that it also provides support for an alternative to CRLs, the Online Certificate Status Protocol (OCSP). With OCSP, the client doesn’t download a potentially large list from the CA’s servers from time to time. Instead, it asks specifically about the validity of one particular certificate that it needs to check in real-time. This results in up-to-date validity information and reduces network and storage requirements, a benefit especially on mobile devices.

Other things like validity periods, mandatory attributes etc. are not only possible but actively enforced by the issuing CA according to its policies.
Conclusion
Of these models, only the hierarchical trust model is considered a Public Key Infrastructure (PKI), so that’s what people refer to when they talk about PKI.
The technical standard in use for this model on the Internet today is X.509, and more specifically the IETF’s variant PKIX.
The next part in this series, part 3, gets back to the practical technical level and shows you how you can inspect and create X.509 certificates with the OpenSSL toolkit.
Google Custom Search Engine allows you to set up search engines with a narrow focus on specialized topics. It features powerful search options and match patterns that let you specify precisely what should and should not end up in the search results.
I set up a custom search engine covering web sites, blogs and mailing list archives related to Mac OS X software development and gave it the following short, easy to remember link:
Try it out right here with something Mac OS X related, for example “IKImageBrowserView”:
The search engine has “Refinements” to focus on results of a particular type, such as reference documentation, mailing list postings etc.:
Usage
Bookmarklet
For frequent use, here is a bookmarklet:
Drag it to your browser’s bookmarks bar:
Then select some text on a web page and click the bookmarklet button you created to search for the text in the Mac development search engine.
LaunchBar/Quicksilver etc.
If you use an application launcher such as LaunchBar or QuickSilver, you can define a search template. In LaunchBar I use this search template with a name/abbreviation of “macdev”:
http://www.google.com/cse?cx=003121735520996018220%3A_bu0g4hqtke&ie=UTF-8&sa=Search&q=*
Embed
You can embed the search box into your own pages. Here’s Google’s code do do that:
<form action="http://www.google.com/cse" id="cse-search-box">
<div>
<input type="hidden" name="cx" value="003121735520996018220:_bu0g4hqtke" />
<input type="hidden" name="ie" value="UTF-8" />
<input type="text" name="q" size="31" />
<input type="submit" name="sa" value="Search" />
</div>
</form>
<script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&lang=en">
Coverage
The configuration of the sites it covers currently looks like this:
Let me know if you know additional useful sites that the custom search should cover.
|


