<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CUECQXg-eCp7ImA9WhBWEkk.&quot;"><id>tag:blogger.com,1999:blog-10602853</id><updated>2013-04-06T03:21:00.650-07:00</updated><category term="c++" /><title>Unixjunkie Blog</title><subtitle type="html">Greg Miller's blog about interesting Unix and Mac stuff</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://unixjunkie.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>69</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/UnixjunkieBlog" /><feedburner:info uri="unixjunkieblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;C0cCSXYzeyp7ImA9WxJRE0s.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-8528080488565304521</id><published>2009-05-14T21:16:00.000-07:00</published><updated>2009-05-14T21:17:48.883-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-14T21:17:48.883-07:00</app:edited><title>New gcalc 0.5</title><content type="html">&lt;a href="http://code.google.com/p/uj-gcalc/"&gt;Gcalc&lt;/a&gt; broke a while back because the html on the Google's search results page changed. Gcalc has been updated and you can download the new binary here.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://uj-gcalc.googlecode.com/files/gcalc-0.5.zip"&gt;gcalc-0.5&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/HAVVBvdRszY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/8528080488565304521/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=8528080488565304521" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8528080488565304521?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8528080488565304521?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/HAVVBvdRszY/new-gcalc-05.html" title="New gcalc 0.5" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2009/05/new-gcalc-05.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04ARXc9cCp7ImA9WxJSGEk.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-6953618610675701520</id><published>2009-05-08T21:01:00.000-07:00</published><updated>2009-05-08T22:12:24.968-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-05-08T22:12:24.968-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="c++" /><title>C++: new Foo vs. new Foo()</title><content type="html">Hi folks. It's been a while since I last posted anything. My family and I moved from the valley to Seattle. We love it up here but we've been very busy.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, on to something somewhat interesting...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Question: In C++, what's the difference between the following&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new Foo;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new Foo();&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;Give up (I almost did)? They're both valid and they both return a pointer to a newly constructed &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Foo&lt;/span&gt; on the heap. They only produce different results when &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;Foo&lt;/span&gt; is a &lt;a href="http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html"&gt;POD type&lt;/a&gt;. In a nutshell, a POD (Plain Ol' Data) type is a class/struct that only contains data members that are scalar types (int, unsigned char, float, bool, etc.) or other POD types. Basically, a POD object looks like an old C-style struct. For example:&lt;/div&gt;&lt;div&gt;(sorry about the lack of indentation—blogger ate it)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new'; "&gt;// POD&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;class Foo {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; public:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  int a;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;// NOT a pod&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;class Bar {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; public:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  int a;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  string name;  // not a POD type&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;The difference between &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new Foo&lt;/span&gt; and &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new Foo() &lt;/span&gt;is that former will be uninitialized and the latter will be default initialized (to zero) when Foo is a POD type. So, when not using the form with the parens, the member "a" can contain garbage, but with the parens "a" will always be initialized to 0. Let's see:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$ &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;cat pod.cc &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;#include &lt;cstdio&gt;&lt;/cstdio&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;struct Foo {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; int a;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;int main() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  Foo* foo = new Foo;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  foo-&gt;a = 7;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  &lt;/span&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;delete foo;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  Foo* &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new_foo&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; = new Foo;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  printf("&lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new_foo&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;-&gt;a = %d\n", &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new_foo&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;-&gt;a);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  delete new_foo;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;  return 0;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$&lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt; g++ -o pod pod.cc &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;$ &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;./pod &lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;new_foo-&gt;a = 7&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But if we simply add empty parens to our new Foo, we'll get different behavior (again, this is only because Foo is a POD type).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;$ &lt;b&gt;cat pod.cc&lt;/b&gt; &lt;/div&gt;&lt;div&gt;#include &lt;cstdio&gt;&lt;/cstdio&gt;&lt;/div&gt;&lt;div&gt;struct Foo {&lt;/div&gt;&lt;div&gt; int a;&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;div&gt;int main() {&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;  Foo* foo = new Foo&lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;()&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  foo-&gt;a = 7;&lt;/div&gt;&lt;div&gt;  delete foo;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;  Foo* new_foo = new Foo&lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;()&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  printf("new_foo-&gt;a = %d\n", new_foo-&gt;a);&lt;/div&gt;&lt;div&gt;  delete new_foo;&lt;/div&gt;&lt;div&gt;  return 0;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;$ &lt;b&gt;g++ -o pod pod.cc&lt;/b&gt; &lt;/div&gt;&lt;div&gt;$&lt;b&gt; ./pod &lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="color:#FF0000;"&gt;new_foo-&gt;a = 0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And that's about it. The two forms are nearly identical. They behave the same except when used on a POD type, in which case the form with parens initializes the members to zero.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Perhaps not that useful, but somewhat interesting.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/2SA259l67Qg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/6953618610675701520/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=6953618610675701520" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6953618610675701520?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6953618610675701520?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/2SA259l67Qg/c-new-foo-vs-new-foo.html" title="C++: &lt;code&gt;new Foo&lt;/code&gt; vs. &lt;code&gt;new Foo()&lt;/code&gt;" /><author><name>Greg Miller</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2009/05/c-new-foo-vs-new-foo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMEQXwzcCp7ImA9WxRWEEU.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-2824572528901330330</id><published>2008-10-26T22:21:00.000-07:00</published><updated>2008-10-26T23:03:20.288-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-26T23:03:20.288-07:00</app:edited><title>Comcast's Incompetence Puts You at Risk</title><content type="html">I'm moving soon and I'm trying to get Comcast setup at the new location. I went through their online ordering process, and aside from the fact that there was no useful information given to differentiate one "package" from another, the process wasn't too painful... until the last step.&lt;br /&gt;&lt;br /&gt;At the end of the process, they require that you chat with a representative online in this shoddy Java applet. I assumed the representative would simply verify some information, then wrap things up. But actually, she said that she needed my SSN. She also reassured me numerous times that "COMCAST is all about protecting customer confidentiality", and that my "information is secured and cannot be viewed by anyone else." Hmm, I thought to myself, I do see that this applet was loaded on a page fetched using https, but how do I know that the applet itself is communicating with the server securely?&lt;br /&gt;&lt;br /&gt;So, of course I immediately started tcpdumping the session.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;sudo tcpdump -s0 -i en1 -A &lt;/b&gt;&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And sure enough, I started seeing unencrypted communication between the applet and the server.&lt;br /&gt;&lt;br /&gt;(applet -&gt; server)&lt;br /&gt;&lt;pre&gt;21:54:36.590164 IP 10.0.1.198.60082 &gt; 66.179.151.44.&lt;b&gt;http&lt;/b&gt;: P 26477:27264(787) ack 37992 win 65535&lt;br /&gt;E..;.N@.@...&lt;br /&gt;...B..,...P...0.6..P...,e..&lt;b&gt;GET /sdccommon/lachat/poll/send_msg.asp?fmt=sst&amp;dtype=msg&amp;Msg=... HTTP/1.1&lt;/b&gt;&lt;br /&gt;Cache-Control: no-cache&lt;br /&gt;Pragma: no-cache&lt;br /&gt;User-Agent: Mozilla/4.0 (Mac OS X 10.5.5) Java/1.5.0_16&lt;br /&gt;Host: www.comcastsupport.com&lt;br /&gt;Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2&lt;br /&gt;Connection: keep-alive&lt;br /&gt;Cookie: CCSSLB=XXXXXXXXXXXXXX; ASPSESSIONIDQSTACRRA=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX; &lt;br /&gt;dbsession=XXXXXXXXXXXXXXXXXXXXX; ASPSESSIONIDQQQAAQRA=XXXXXXXXXXXXXXXXXXXXX&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(server -&gt; applet)&lt;br /&gt;&lt;pre&gt;21:55:54.626048 IP 66.179.151.44.&lt;b&gt;http&lt;/b&gt; &gt; 10.0.1.198.60082: P 54493:55606(1113) ack 39154 win 65535&lt;br /&gt;E...V.@.p...B..,&lt;br /&gt;....P...6......P..._...HTTP/1.1 200 OK&lt;br /&gt;Date: Mon, 27 Oct 2008 04:55:55 GMT&lt;br /&gt;Server: Microsoft-IIS/6.0&lt;br /&gt;X-Server: sg-ec-ch05&lt;br /&gt;X-Powered-By: ASP.NET&lt;br /&gt;Pragma: no-cache&lt;br /&gt;Content-Length: 842&lt;br /&gt;Content-Type: text/xml; Charset=utf-8&lt;br /&gt;Expires: Mon, 27 Oct 2008 04:54:55 GMT&lt;br /&gt;Cache-control: no-cache&lt;br /&gt;&lt;br /&gt;REQUEST_TYPE=STATUS-POLL&lt;br /&gt;USER{&lt;br /&gt;  USER_NAME&amp;lt;Adela&amp;gt;USER_NAME&lt;br /&gt;  TYPING=false&lt;br /&gt;  SI=&lt;br /&gt;  RC=&lt;br /&gt;  CMD=&lt;br /&gt;  IDENT=&lt;br /&gt;  USER_TYPE=analyst&lt;br /&gt;  EMAIL_ADDR=Auto Invitation&lt;br /&gt;  STATUS=working&lt;br /&gt;  PROBLEM &amp;lt;Order Information&amp;gt;PROBLEM&lt;br /&gt;  ROOM=XXXXXXXXXXXXXXXXXXXXXXXXXXXX&lt;br /&gt;USER}&lt;br /&gt;USER{&lt;br /&gt;  USER_NAME&amp;lt;James_&amp;gt;USER_NAME&lt;br /&gt;  TYPING=false&lt;br /&gt;  SI=&lt;br /&gt;  RC=&lt;br /&gt;  CMD=&lt;br /&gt;  IDENT=&lt;br /&gt;  USER_TYPE=user&lt;br /&gt;  EMAIL_ADDR=&lt;br /&gt;  STATUS=working&lt;br /&gt;  PROBLEM&amp;lt;Order Information&amp;gt;PROBLEM&lt;br /&gt;  ROOM= XXXXXXXXXXXXXXXXXXXXXXXXXXXX&lt;br /&gt;USER}&lt;br /&gt;MSG{&lt;br /&gt;  ID=XXXXXXXXXXXXX&lt;br /&gt;  TYPE=msg&lt;br /&gt;  FROM&amp;lt;Adela&amp;gt;FROM&lt;br /&gt;  TEXT&amp;lt;&lt;b&gt;Okay, no problem then. If you really think that this chat is not secure, you can call...&lt;/b&gt;&amp;gt;TEXT&lt;br /&gt;  TIME&amp;lt;10/27/2008 12:55:52 AM&amp;gt;TIME&lt;br /&gt;MSG}&lt;br /&gt;QUEUE{&lt;br /&gt;   NAME&amp;lt;sales6&amp;gt;NAME&lt;br /&gt;   ID=XXXXXXXXXXX&lt;br /&gt;   COUNT=0&lt;br /&gt;   AHEAD=0&lt;br /&gt;QUEUE}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the end, the chat channel clearly was not encrypted. And during the conversation they send your name, address, phone, &lt;em&gt;and SSN&lt;/em&gt; through this chat session, and they claim that the information is secured.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-gdIE3zOOOA/SQVXF6gRENI/AAAAAAAAAA0/0Qnw1sNNLpk/s1600-h/Picture+2.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 182px;" src="http://4.bp.blogspot.com/_-gdIE3zOOOA/SQVXF6gRENI/AAAAAAAAAA0/0Qnw1sNNLpk/s200/Picture+2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5261707498767847634" /&gt;&lt;/a&gt;&lt;br /&gt;I would advise everyone to NOT trust online orders with Comcast, especially ones that use the Java applet pictured here. Or perhaps the better advice is to just not trust anything with the word "Comcast" on it (except for this blog post). &lt;br /&gt;&lt;br /&gt;I don't know why I'm still amazed by their consistent incompetence.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/fwJyXMAmMWY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/2824572528901330330/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=2824572528901330330" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2824572528901330330?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2824572528901330330?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/fwJyXMAmMWY/comcasts-incompetence-puts-you-at-risk.html" title="Comcast's Incompetence Puts You at Risk" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_-gdIE3zOOOA/SQVXF6gRENI/AAAAAAAAAA0/0Qnw1sNNLpk/s72-c/Picture+2.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2008/10/comcasts-incompetence-puts-you-at-risk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQFRXw4fyp7ImA9WxRRF0k.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-5552566080949539325</id><published>2008-09-29T19:59:00.000-07:00</published><updated>2008-09-29T20:11:54.237-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-29T20:11:54.237-07:00</app:edited><title>Update Engine</title><content type="html">&lt;a href="http://code.google.com/p/update-engine"&gt;&lt;img src="http://update-engine.googlecode.com/svn/site/update-engine-small.gif" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Today we announced a new open source project called &lt;a href="http://code.google.com/p/update-engine"&gt;Update Engine&lt;/a&gt;. Update Engine is a framework to help developers keep their software up-to-date. See the &lt;a href="http://googlemac.blogspot.com/2008/09/revving-software-with-update-engine.html"&gt;Google Mac blog&lt;/a&gt; post for a quick overview and a link to some demo movies explaining Update Engine [and yes, I knew I sounded like kermit when I recorded the video—I even told my wife but she didn't think so... oh well ;-)].&lt;br /&gt;&lt;br /&gt;Also, we did not build Update Engine to compete with &lt;a href="http://sparkle.andymatuschak.org/"&gt;Sparkle&lt;/a&gt;. We built Update Engine to solve different problems. If you're interested, &lt;a href="http://groups.google.com/group/update-engine/browse_thread/thread/f4f97b67c17fcce2"&gt;here's my reply&lt;/a&gt; about this in the Google Group for the project.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/34tcojro6iA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/5552566080949539325/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=5552566080949539325" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/5552566080949539325?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/5552566080949539325?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/34tcojro6iA/update-engine.html" title="Update Engine" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2008/09/update-engine.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUDQXw-eCp7ImA9WxZaEk8.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-8628135296281598827</id><published>2008-04-26T08:16:00.000-07:00</published><updated>2008-04-26T08:21:10.250-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-26T08:21:10.250-07:00</app:edited><title>Gcalc Update</title><content type="html">I updated &lt;a href="http://code.google.com/p/uj-gcalc/"&gt;gcalc&lt;/a&gt; to fix an issue caused by Google changing the HTML around the Google calculator answers (they added an extra h2 tag). No biggie, but gcalc now works again. You can get the new version &lt;a href="http://code.google.com/p/uj-gcalc/downloads/list"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Also, I made gcalc a (small) code.google.com project. So you can now check it out at &lt;a href="http://code.google.com/p/uj-gcalc/"&gt;http://code.google.com/p/uj-gcalc/&lt;/a&gt;.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/cgfe-UL8W7Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/8628135296281598827/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=8628135296281598827" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8628135296281598827?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8628135296281598827?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/cgfe-UL8W7Q/gcalc-update.html" title="Gcalc Update" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2008/04/gcalc-update.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAGQnk4fip7ImA9WxZUGEU.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-1340994916776732185</id><published>2008-04-10T21:14:00.000-07:00</published><updated>2008-04-10T21:22:03.736-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-10T21:22:03.736-07:00</app:edited><title>Locating Apps from the Command Line</title><content type="html">The other day I needed to find the location of an application using its bundle ID. Easy, just use LaunchServices. But I needed to do this from a script. Here are a couple perl one-liners to do it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;perl -MMac::Processes -e 'printf "%s\n", LSFindApplicationForInfo(undef, "com.apple.TextEdit")'&lt;/b&gt;&lt;br /&gt;/Applications/TextEdit.app&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;mv /Applications/TextEdit.app ~/Desktop/&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;perl -MMac::Processes -e 'printf "%s\n", LSFindApplicationForInfo(undef, "com.apple.TextEdit")'&lt;/b&gt;&lt;br /&gt;/Users/jgm/Desktop/TextEdit.app&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;mv ~/Desktop/TextEdit.app /Applications/&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;perl -MMac::Processes -e 'printf "%s\n", LSFindApplicationForInfo(undef, undef, "TextEdit.app")'&lt;/b&gt;&lt;br /&gt;/Applications/TextEdit.app&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(Yes, I know &lt;code&gt;mdfind&lt;/code&gt; could do something similar. But it wouldn't necessarily return the one that LaunchServices thinks is the "preferred" one if there were multiple applications with the same bundle ID.)&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/LR0jHEAn-UE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/1340994916776732185/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=1340994916776732185" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1340994916776732185?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1340994916776732185?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/LR0jHEAn-UE/locating-apps-from-command-line.html" title="Locating Apps from the Command Line" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2008/04/locating-apps-from-command-line.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcDSH8-cCp7ImA9WxZWFk0.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-3169111945252284783</id><published>2008-03-15T09:45:00.000-07:00</published><updated>2008-03-15T11:01:19.158-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-15T11:01:19.158-07:00</app:edited><title>id vs NSObject* vs id&lt;NSObject&gt;</title><content type="html">There's often confusion about the difference between the following three declarations in Objective-C:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;id           foo1;&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;NSObject    *foo2;&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;id&amp;lt;NSObject&amp;gt; foo3;&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;The first one is the most common. It simply declares a pointer to some Objective-C object (see &lt;a href="http://www.opensource.apple.com/darwinsource/10.5.2/objc4-371.1/runtime/objc.h"&gt;/usr/include/objc/objc.h&lt;/a&gt;). &lt;code&gt;id&lt;/code&gt; gives the compiler no information about the actual type of the object, so the compiler cannot do compile-time type checking for you. Thus, the compiler will let you send any (*) message to objects declared &lt;code&gt;id&lt;/code&gt;. Actually, this is why the common idiom of &lt;code&gt; [[Foo alloc] init]&lt;/code&gt; doesn't cause the compiler to complain. &lt;code&gt;+alloc&lt;/code&gt; is declared to return type &lt;code&gt;id&lt;/code&gt;, so the compiler won't yell when you then send the returned object the message &lt;code&gt;init&lt;/code&gt; (or even &lt;code&gt;initWithMyFoo:blah&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;So, objects declared using &lt;code&gt;id&lt;/code&gt; are just dynamically typed at runtime. The compiler has no useful information about the object's real type, so it can't warn you if you send it a message that it may not respond to.&lt;br /&gt;&lt;br /&gt;Just because we know that an &lt;code&gt;id&lt;/code&gt; is an Objective-C object does &lt;b&gt;not&lt;/b&gt; mean that it points to an object that derives from NSObject, or that it even has common methods like retain and release. One solution is to statically type our variable using &lt;code&gt;NSObject*&lt;/code&gt; as shown in number 2 above. This gives the compiler information about the class of the object pointed to by &lt;code&gt;foo2&lt;/code&gt; so the compiler can warn if you send a message to &lt;code&gt;foo2&lt;/code&gt; that an &lt;code&gt;NSObject&lt;/code&gt; doesn't respond to. This means you can safely call retain, release, description, etc., but the compiler will warn if you call &lt;code&gt;length&lt;/code&gt; or &lt;code&gt;count&lt;/code&gt; or anything that an NSObject doesn't respond to.&lt;br /&gt;&lt;br /&gt;So, declaring a generic pointer of type NSObject* is very similar to what you would do in other languages, like Java, but it's really a bit too restrictive for a language as flexible as Objective-C. Despite what you may have learned at one point, not all Foundation/Cocoa objects derive from NSObject. As an example, NSProxy is not derived from NSObject, so the &lt;code&gt;foo2&lt;/code&gt; pointer above would not be able to hold an NSProxy subclass, even though NSProxy does implement common methods like retain and release. What you really want is a pointer to &lt;i&gt;any&lt;/i&gt; object that behaves like an NSObject. And that's exactly what the third case does.&lt;br /&gt;&lt;br /&gt;Declaring an object as &lt;code&gt;id&amp;lt;NSObject&amp;gt;&lt;/code&gt; tells the compiler that you don't care what type the object is, but you do care that it conforms to the specified NSObject protocol**. The compiler will ensure that all objects you assign to that pointer conform to the required protocol. A pointer typed like this can safely hold any NSObject (because NSObject conforms to the NSObject protocol), but it could also hold any NSProxy, because NSProxy also conforms to the NSObject protocol. In english, the declaration  &lt;code&gt;id&amp;lt;NSObject&amp;gt; foo3;&lt;/code&gt; says "foo3 is a pointer to an object of any type that behaves like an NSObject". This is very powerful, convenient, and expressive. In reality, we often don't care what type an object is, we just care that it responds to the messages that we want to send it (e.g., retain, release). &lt;br /&gt;&lt;br /&gt;So how do you decide which form you want to use? It's pretty easy. If you don't want (or can't have) any type checking, then use a plain &lt;code&gt;id&lt;/code&gt;. This is very common for return types on methods that don't know the type of object they're returning (e.g., &lt;code&gt;+alloc&lt;/code&gt;). It is also common to declare delegates to be type &lt;code&gt;id&lt;/code&gt;, because delegates are generally checked at runtime with &lt;code&gt;respondsToSelector:&lt;/code&gt;, and they usually aren't retained. &lt;br /&gt;&lt;br /&gt;However, if you do want compile-time type checking, you must decide between the second and third cases. Well, let me just help you out&amp;mdash;you want the third case! :-) I've very, very, VERY rarely seen a situation where &lt;code&gt;NSObject *&lt;/code&gt; worked but &lt;code&gt;id&amp;lt;NSObject&amp;gt;&lt;/code&gt; would not. And using the protocol form has the advantage that it will work with NSProxys. You may think that you never use NSProxys, but Cocoa's distributed objects system makes heavy use of NSProxy subclasses. Additionally, the common case is that you simply want to ensure that an object can be retained or released, and in that case the protocol form conveys that intent better; you really don't care what class the object is, you only care that it &lt;i&gt;behaves&lt;/i&gt; like an NSObject.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;* Well, not "any" message. If you send a message using a selector that the compiler has never seen, it may warn that it has never seen that selector. This is nice in the event that you mistype &lt;code&gt;init&lt;/code&gt; as &lt;code&gt;inti&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;** Now, when I say "NSObject" here I'm talking about the protocol (&lt;code&gt;@protocol&lt;/code&gt;) named NSObject. There is also a &lt;i&gt;class&lt;/i&gt; named NSObject that does indeed conform to the NSObject protocol, but they are two different things.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/uV1e9rUq0QI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/3169111945252284783/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=3169111945252284783" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/3169111945252284783?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/3169111945252284783?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/uV1e9rUq0QI/id-vs-nsobject-vs-id.html" title="&lt;code&gt;id&lt;/code&gt; vs &lt;code&gt;NSObject*&lt;/code&gt; vs &lt;code&gt;id&amp;lt;NSObject&amp;gt;&lt;/code&gt;" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2008/03/id-vs-nsobject-vs-id.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4MQHg9eip7ImA9WxZTFU4.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-575536475085906387</id><published>2008-01-16T18:41:00.000-08:00</published><updated>2008-01-16T18:46:21.662-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-16T18:46:21.662-08:00</app:edited><title>Great Macworld Pics</title><content type="html">Markd over at the &lt;a href="http://borkwarellc.wordpress.com/2008/01/16/macworld-2008/"&gt;Borkware Miniblog&lt;/a&gt; posted some great pictures&amp;mdash;and hilarious captions&amp;mdash;of Macworld '08.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/9tihSxdtunQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/575536475085906387/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=575536475085906387" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/575536475085906387?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/575536475085906387?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/9tihSxdtunQ/great-macworld-pics.html" title="Great Macworld Pics" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2008/01/great-macworld-pics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QHSH8_fCp7ImA9WB9bFUk.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-6420423545529719095</id><published>2007-12-24T16:08:00.001-08:00</published><updated>2007-12-24T16:08:59.144-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-24T16:08:59.144-08:00</app:edited><title>A good read: Inside the Machine</title><content type="html">&lt;img src="http://books.google.com/books?id=Q1zSIarI8xoC&amp;dq=inside+the+machine&amp;printsec=frontcover&amp;img=1&amp;zoom=5" align="left" /&gt;&lt;br /&gt;I just finished reading the book &lt;a href="http://www.amazon.com/Inside-Machine-Introduction-Microprocessors-Architecture/dp/1593271042/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1198539374&amp;amp;sr=8-1"&gt;Inside the Machine: An Illustrated Introduction to Microprocessors and Computer Architecture&lt;/a&gt;, by Jon Stokes, and it was fantastic. It is an extremely thorough, yet very approachable, explanation of microprocessor architecture, and it uses popular Intel processors and PowerPC processors as the examples. It even covers up through Intel's Core 2 Duo chips. &lt;br /&gt;&lt;br /&gt;It's probably too late to put this on your holiday wish list, so I'd recommend that you just treat yourself to a new geeky book. &lt;br /&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/8EowGulLyg8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/6420423545529719095/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=6420423545529719095" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6420423545529719095?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6420423545529719095?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/8EowGulLyg8/good-read-inside-machine.html" title="A good read: Inside the Machine" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/12/good-read-inside-machine.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EMQHs5fSp7ImA9WB9UEkg.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-8852058143981828757</id><published>2007-12-08T17:37:00.001-08:00</published><updated>2007-12-09T17:54:41.525-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-12-09T17:54:41.525-08:00</app:edited><title>New iPhone</title><content type="html">About a month ago I noticed the WiFi on my 8GB iPhone starting to get a little flakey. My iPhone would no longer connect to my home network, which is basically an AirPort Extreme closed network using WPA2 and MAC address filtering; just the standard wireless stuff. I didn't want to believe that the phone was broken because then I'd have to send it in and spend a week without a phone, or talk to a "genius" and beg for a new phone or something, so I just kept putting off digging into the problem any further. If I tried a restore and it didn't fix it, then I'd be forced to go through all the hassle that I desperately wanted to avoid. &lt;br /&gt;&lt;br /&gt;Over my two week Thanksgiving holiday trip in Chicago and Ohio my iPhone took another turn for the worse. During our flight back to California we ended up stranded in Chicago—sitting on the plane—for 9 hours before finally taking off for the 5 hour flight. (My wife and I also had our 4 month old daughter with us during this most enjoyable time.) Then it happened. About 1 hour into our 9 hour wait (14 hours total) my iPhone battery died and I had barely been using the phone! Now I was unable to get weather updates, catch up on Family Guy, or use the free O'Hare WiFi that I could still reach from the plane. It was terrible.&lt;br /&gt;&lt;br /&gt;When I got back I realized that something was really wrong with my iPhone. With a full charge it would only last for about 6–8 hours with &lt;strong&gt;no&lt;/strong&gt; use! Now I had no choice but to take it in to the geniuses at the Apple store.&lt;br /&gt;&lt;br /&gt;Anyway, to make a long story not too much longer, I brought my broken iPhone into the Apple store, talked to a genius and she cheerfully grabbed a brand new 8GB iPhone for me, switched out the SIM card, and sent me on my way in a matter of minutes. I was so pleasantly surprised about how fantastic and easy the iPhone support was. It was great. I should have done this a month ago! Thanks Apple.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/ba_1hY_ilss" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/8852058143981828757/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=8852058143981828757" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8852058143981828757?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8852058143981828757?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/ba_1hY_ilss/new-iphone.html" title="New iPhone" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/12/new-iphone.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8ARX44eCp7ImA9WB9QGEs.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-8744247299260442240</id><published>2007-10-31T14:32:00.001-07:00</published><updated>2007-10-31T14:40:44.030-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-31T14:40:44.030-07:00</app:edited><title>DTrace article</title><content type="html">&lt;a href="http://www.mactech.com/articles/mactech/Vol.23/23.11/ExploringLeopardwithDTrace/index.html"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://mactech.com/mt_covers/cover-2007/MT-Cover-0711.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;I wrote an article about &lt;a href="http://www.mactech.com/articles/mactech/Vol.23/23.11/ExploringLeopardwithDTrace/index.html"&gt;Exploring Leopard with DTrace&lt;/a&gt; for &lt;a href="http://www.mactech.com/"&gt;MacTech&lt;/a&gt; Magazine. Check it out when you get a chance. It was very fun to write because DTrace is just so totally freaking awesome. The most difficult part of writing it was limiting it to "magazine length"&amp;mdash;I felt like I could go on for a few hundred pages.&lt;br /&gt;&lt;br /&gt;Now that this is out, I'll probably start posting some DTrace fun on this blog as I get time.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/a92m1FwG8RA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/8744247299260442240/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=8744247299260442240" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8744247299260442240?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8744247299260442240?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/a92m1FwG8RA/dtrace-article.html" title="DTrace article" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/10/dtrace-article.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04CSHY9fSp7ImA9WB9QF00.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-2032496991760965799</id><published>2007-10-29T16:51:00.001-07:00</published><updated>2007-10-29T16:52:49.865-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-29T16:52:49.865-07:00</app:edited><title>Better compile-time assertions</title><content type="html">In a previous post I talked about one way to do &lt;a href="http://unixjunkie.blogspot.com/2007/09/compile-time-asserts.html"&gt;compile-time assertions&lt;/a&gt; in C and Objective-C. The example used works fine, but it has some drawbacks. Specifically, each call to &lt;code&gt;COMPILE_ASSERT&lt;/code&gt;&lt;sup&gt;*&lt;/sup&gt; needs to have a unique message string, otherwise an error is given due to the attempt to redefine a typedef.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;cat -n compile_assert.c &lt;/b&gt;&lt;br /&gt;     1 #define COMPILE_ASSERT(test, msg) typedef char _COMPILE_ASSERT_ ## msg [ ((test) ? 1 : -1) ]&lt;br /&gt;     2 int main(void) {&lt;br /&gt;     3   COMPILE_ASSERT(1 == 1, blah);&lt;br /&gt;     4   COMPILE_ASSERT(2 == 2, blah);&lt;br /&gt;     5   return 0;&lt;br /&gt;     6 }&lt;br /&gt;$ &lt;b&gt;gcc -Wall compile_assert.c &lt;/b&gt;&lt;br /&gt;compile_assert.c: In function ‘main’:&lt;br /&gt;compile_assert.c:4: error: redefinition of typedef ‘_COMPILE_ASSERT_blah’&lt;br /&gt;compile_assert.c:3: error: previous declaration of ‘_COMPILE_ASSERT_blah’ was here&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One obvious and easy solution to this problem is to put each typedef in its own lexical scope by wrapping it in a &lt;code&gt;do { ... } while (0)&lt;/code&gt;. This would work, but then we would lose the ability to use the compile-time assertions in global scope or in header files. With regular runtime assertions this probably isn't a big deal, but having compile-time assertions in a header can be incredibly useful. For example, your code may expose some tweakable knobs by &lt;code&gt;#define&lt;/code&gt;ing constants, but it might be important that one of the constants is always less than another. This is a perfect place to use a compile-time assertion. Having the assertion itself right in the header file will help ensure the code's correctness and can also serve as a form of documentation.&lt;br /&gt;&lt;br /&gt;Since we want to retain the ability to use these assertions anywhere, including in headers, we need to find another solution. Well, another solution is to make sure the typedef'd identifier is unique. We could simply put this burden on the caller and tell them that their message strings must be unique within a given scope (which probably isn't that big of a burden in reality), but we can do better.&lt;br /&gt;&lt;br /&gt;We can use the C preprocessor symbol &lt;code&gt;__LINE__&lt;/code&gt; to include the current line number in the typedef identifier name. That should guarantee that the identifiers are unique in most cases (there are some corner cases where this is not exactly true). The only trick here is rigging up the preprocessor macros to do what we want. Here are the macros that I came up with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;cat -n compile_assert_NEW.c &lt;/b&gt;&lt;br /&gt;     1 #define _COMPILE_ASSERT_SYMBOL_INNER(line, msg) __COMPILE_ASSERT_ ## line ## __ ## msg&lt;br /&gt;     2 #define _COMPILE_ASSERT_SYMBOL(line, msg) _COMPILE_ASSERT_SYMBOL_INNER(line, msg)&lt;br /&gt;     3 #define COMPILE_ASSERT(test, msg) \&lt;br /&gt;     4   typedef char _COMPILE_ASSERT_SYMBOL(__LINE__, msg) [ ((test) ? 1 : -1) ]&lt;br /&gt;     5 &lt;br /&gt;     6 COMPILE_ASSERT(1 == 1, foo);&lt;br /&gt;     7 COMPILE_ASSERT(2 == 2, foo);&lt;br /&gt;     8 &lt;br /&gt;     9 int main(void) {&lt;br /&gt;    10   return 0;&lt;br /&gt;    11 }&lt;br /&gt;$ &lt;b&gt;gcc -Wall compile_assert_NEW.c &lt;/b&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can see that the usage of &lt;code&gt;COMPILE_ASSERT&lt;/code&gt; worked two times in a row, with the exact same message string, and it worked in the global scope. This is just what we wanted.&lt;br /&gt;&lt;br /&gt;The weird part is that we need 3 levels of macros, and one of them doesn't look like it actually does anything at all (the one on line 2). The macro on line 2 is needed because of the way in which the preprocessor expands macros. Macros are expanded by doing multiple passes over a given line until all the macros have been evaluated. However, once a macro is expanded the resulting tokens are not again checked for more macros until the next pass. This is explained in section 12.3 of &lt;a href="http://www.amazon.com/exec/obidos/ASIN/0131103709"&gt;The C Programming Language, Second Edition&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Also, when writing and debugging macros, it's very useful to use &lt;code&gt;gcc -E&lt;/code&gt; which stops after the preprocessing stage and dumps the preprocessed file to standard output.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;gcc -E compile_assert_NEW.c &lt;/b&gt;&lt;br /&gt;# 1 "compile_assert_NEW.c"&lt;br /&gt;# 1 "&lt;built-in&gt;"&lt;br /&gt;# 1 "&lt;command line&gt;"&lt;br /&gt;# 1 "compile_assert_NEW.c"&lt;br /&gt;&lt;br /&gt;typedef char __COMPILE_ASSERT_6__foo [ ((1 == 1) ? 1 : -1) ];&lt;br /&gt;typedef char __COMPILE_ASSERT_7__foo [ ((1 == 1) ? 1 : -1) ];&lt;br /&gt;&lt;br /&gt;int main(void) {&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;sup&gt;*&lt;/sup&gt; in the previous blog post I called it "STATIC_ASSERT", but I'm now calling it "COMPILE_ASSERT" because the word "static" is too overloaded&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/D2ONhz-e_48" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/2032496991760965799/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=2032496991760965799" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2032496991760965799?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2032496991760965799?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/D2ONhz-e_48/better-compile-time-asserts_29.html" title="Better compile-time assertions" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU4HRXk8fSp7ImA9WB9QFk4.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-5139714217258926922</id><published>2007-10-28T22:02:00.000-07:00</published><updated>2007-10-28T23:05:34.775-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-28T23:05:34.775-07:00</app:edited><title>Annoying Comcast UI</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-gdIE3zOOOA/RyVp2l19u5I/AAAAAAAAAAM/oLl9vdcx2B4/s1600-h/IMG_1080.JPG"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_-gdIE3zOOOA/RyVp2l19u5I/AAAAAAAAAAM/oLl9vdcx2B4/s400/IMG_1080.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5126620137423485842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I am certainly no UI guru&amp;mdash;my favorite UI is a Unix shell. But I think Comcast's DVR user interface is perhaps the worst UI ever; at least in the top (or would it be bottom?) 10. It seems like it's always doing exactly what I don't want. Nothing is intuitive. It gets in my way. It irritates me ever single day.&lt;br /&gt;&lt;br /&gt;Here is an example of one of the Comcast DVR's idiotic UIs. I was recording &lt;a href="http://www.imdb.com/title/tt0372183/"&gt;The Bourne Supremacy&lt;/a&gt; when I decided to quickly change channels to see what was on the news. Instead of just changing the channel, it wasted my time with this idiotic question asking whether I wanted to stop the recording and change the channel or just change the channel. How dumb!? Just change the friggin' channel&amp;mdash;that's what I told it to do in the first place. At least this time the destructive action wasn't the default.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/7WKhOGgdOvc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/5139714217258926922/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=5139714217258926922" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/5139714217258926922?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/5139714217258926922?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/7WKhOGgdOvc/i-am-certainly-no-ui-guru-favorite-ui.html" title="Annoying Comcast UI" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_-gdIE3zOOOA/RyVp2l19u5I/AAAAAAAAAAM/oLl9vdcx2B4/s72-c/IMG_1080.JPG" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/10/i-am-certainly-no-ui-guru-favorite-ui.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMESXkzfSp7ImA9WB9REUg.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-2362537937739390459</id><published>2007-10-11T17:17:00.001-07:00</published><updated>2007-10-11T17:53:28.785-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-11T17:53:28.785-07:00</app:edited><title>Generating Random Words</title><content type="html">I was screwing around this morning and I needed some random words to test something with. The words needed to be &lt;em&gt;real&lt;/em&gt; words, not just random sequences of characters (btw, you can generate a random sequence of 8 characters from the shell using &lt;code&gt;jot -r -c 8 a z | rs -g 0 8&lt;/code&gt;). In this case, I decided to simply grab a random word from &lt;code&gt;/usr/share/dict/words&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Hmm, but how do I grab a random word from a file? My solution was to generate a random number in the range &lt;code&gt;[1..n]&lt;/code&gt; where &lt;code&gt;n&lt;/code&gt; is the number of lines in the file, &lt;code&gt;cat -n&lt;/code&gt; the file so that line numbers are printed, &lt;code&gt;grep&lt;/code&gt; for the line matching the random number, then print out the second column. It looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;n=$(cat /usr/share/dict/words | wc -l)&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;cat -n /usr/share/dict/words | grep -w $(jot -r 1 1 $n) | cut -f2&lt;/b&gt;&lt;br /&gt;idic&lt;br /&gt;$ &lt;b&gt;cat -n /usr/share/dict/words | grep -w $(jot -r 1 1 $n) | cut -f2&lt;/b&gt;&lt;br /&gt;goldentop&lt;br /&gt;$ &lt;b&gt;cat -n /usr/share/dict/words | grep -w $(jot -r 1 1 $n) | cut -f2&lt;/b&gt;&lt;br /&gt;Hamitism&lt;br /&gt;$ &lt;b&gt;cat -n /usr/share/dict/words | grep -w $(jot -r 1 1 $n) | cut -f2&lt;/b&gt;&lt;br /&gt;accumulativeness&lt;br /&gt;$ &lt;b&gt;cat -n /usr/share/dict/words | grep -w $(jot -r 1 1 $n) | cut -f2&lt;/b&gt;&lt;br /&gt;ratihabition&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, this solution is certainly not cryptographically sound, but it should serve for quick, ad-hoc testing.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/Nb5qcZaQmX0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/2362537937739390459/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=2362537937739390459" title="12 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2362537937739390459?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2362537937739390459?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/Nb5qcZaQmX0/generating-random-words.html" title="Generating Random Words" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>12</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/10/generating-random-words.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcCSHo7cSp7ImA9WB9QF00.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-8858381891234518574</id><published>2007-09-20T09:01:00.001-07:00</published><updated>2007-10-29T16:54:29.409-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-10-29T16:54:29.409-07:00</app:edited><title>Compile-time asserts</title><content type="html">I've been pretty busy with the new baby lately and haven't had much time to post anything interesting. That's not necessarily going to change today, but some folks may find this useful anyway.&lt;br /&gt;&lt;br /&gt;There are a few ways to do compile-time asserts that work in C and Objective-C. One way is to simply write a macro that evaluates a boolean expression that can be evaluated at compile time, then in the false case, have it do something illegal that the compiler will complain about.  For example, below we just declare the macro &lt;code&gt;STATIC_ASSERT&lt;/code&gt;, that takes a boolean expression and a message string, and if &lt;code&gt;test&lt;/code&gt; evaluates to false, it will try create a typedef for a char array with a negative size. The compiler will complain, and there you'll have your static assert. The message string is used as part of the typedef name as a way to put useful text in the output, but that means it must not contain any spaces.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#define STATIC_ASSERT(test, msg) typedef char _static_assert_ ## msg [ ((test) ? 1 : -1) ]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And we could use it like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#define STATIC_ASSERT(test, msg) typedef char _static_assert_ ## msg [ ((test) ? 1 : -1) ]&lt;br /&gt;int main() {&lt;br /&gt;  STATIC_ASSERT(sizeof(long) == 4, LONGS_MUST_BE_4_BYTES);&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And if the assertion fails, you'll see an error like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ &lt;b&gt;gcc -o test test.c&lt;/b&gt;&lt;br /&gt;test.c: In function 'main':&lt;br /&gt;test.c:4: error: size of array '_static_assert_LONGS_MUST_BE_4_BYTES' is negative&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;One reason this trick is cool is that you end up with a nice stoic emoticon in your code. Now, if we can just figure out how to get the "Oh my God! There's an ax in my head." k:-O  (Thanks Mark D)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html"&gt;UPDATE 10/29: This post talks about a more flexible way to do compile-time assertions&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/NbeR1CdlMtY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/8858381891234518574/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=8858381891234518574" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8858381891234518574?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/8858381891234518574?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/NbeR1CdlMtY/compile-time-asserts.html" title="Compile-time asserts" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/09/compile-time-asserts.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4AR345eyp7ImA9WB5VFE4.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-5190534492219601569</id><published>2007-08-06T15:17:00.000-07:00</published><updated>2007-08-06T15:22:26.023-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-08-06T15:22:26.023-07:00</app:edited><title>New little hacker</title><content type="html">My daughter, Vivien, born 8/1/2007.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://lh4.google.com/devjgm/RraHFjB7S9I/AAAAAAAAALY/gRK4XhKsrqw/s400/IMG_0415.JPG" /&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/0OZWRMhMvnE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/5190534492219601569/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=5190534492219601569" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/5190534492219601569?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/5190534492219601569?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/0OZWRMhMvnE/new-little-hacker.html" title="New little hacker" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>13</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/08/new-little-hacker.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04HQnw4fCp7ImA9WB5XE0Q.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-1025636824095589544</id><published>2007-07-13T22:59:00.000-07:00</published><updated>2007-07-14T00:58:53.234-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-07-14T00:58:53.234-07:00</app:edited><title>Values of a Software Engineer</title><content type="html">I originally wrote this as if it were a "best practices" document, but then what are &lt;i&gt;best&lt;/i&gt; practices? Who says they're the best? And what the heck do I know and why would anyone listen to me? So, now it's just a post about software engineering practices that I, personally, value.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;h2&gt;Don't forget to design your code&lt;/h2&gt;&lt;br /&gt;It is extremely important to do some upfront design on all but the most simplistic software. It can even be fun, so it's surprising to see how often it's skipped or glossed over. One reason might be that people start prototyping something, they see that it works, and they get very excited. Then, they start feeling like they're almost done, so they begin fleshing out the prototype to bolt on the rest of the features that the software ultimately needs. Before they know it, they've got a big mess of unmaintainable software that clearly had little forethought. This can be OK for simple projects, but for anything beyond your weekend coding frenzy it's not a good idea. Prototyping is a great way to test new ideas and verify existing assumptions, but don't forget that it's just a prototype.  &lt;br /&gt;&lt;br /&gt;Writing software is not like constructing a building, in that you don't need to have rigorous blueprints with every precise measurement listed down to the last excruciating detail. But you do still need to do a lot of design work prior to writing your software. Software is built using abstract ("soft") concepts and objects, and you need to figure out what these concepts and objects are and how they interact and fit together. You need to study the problem domain in which you're working and figure out how it will map to your code. These objects typically make up the &lt;a href="http://en.wikipedia.org/wiki/Domain_model"&gt;domain model&lt;/a&gt; of your code, and it's very important that they are well thought out and match reality as much as possible. For example, if you and your team always talk about how "a customer has an account", it should be a red flag to see that your code shows the &lt;code&gt;Account&lt;/code&gt; class is the one that "has a" &lt;code&gt;Customer&lt;/code&gt; object (or perhaps they're not related at all in the code). This reality-code mismatch is not uncommon and it can harbor a nasty nest of bugs. These domain objects are often used heavily throughout the code, and a poorly designed domain model can quickly infect the rest of your code.  &lt;br /&gt;&lt;br /&gt; While designing your code you should also be open to new and potentially wild ideas. Sweeping refactorings during design time have a very low cost; you typically only need to change a few figures in &lt;a href="http://www.omnigroup.com/applications/omnigraffle/"&gt;OmniGraffle&lt;/a&gt; or crumple and &lt;strike&gt;throw away&lt;/strike&gt; recycle a &lt;a href="http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card"&gt;CRC card&lt;/a&gt;. Also, be very pragmatic. Don't immediately dismiss an idea just because of one potential complication. Maybe that complication will never actually arise. Maybe only a small percentage of your users will even care about it. If the idea is otherwise brilliant, it may be worth a small price. Don't expect to please everyone; you can't do it. Be pragmatic. Be pragmatic. Be pragmatic.&lt;br /&gt;&lt;br /&gt;Lastly, expect your design to change as you go, because it will; they always do. But this is OK. Once you're in the trenches writing the code, you may discover a much better way to do something. You shouldn't ignore this. Think about the tradeoffs and go with the best idea.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h2&gt;Refactor early and often&lt;/h2&gt;&lt;br /&gt;Most software engineers today understand that software development is an iterative process, they know what refactoring is and most say they do it. However, there is often a gray area around when and what to refactor and whether or not it's too late to refactor. One common argument against refactoring is that there's no time for it. But as J. Hank Rainwater said in his book &lt;a href="http://www.amazon.com/Herding-Cats-Primer-Programmers-Lead/dp/1590590171/ref=sr_1_1/002-6420967-0871248?ie=UTF8&amp;s=books&amp;qid=1184394445&amp;sr=8-1"&gt;Herding Cats: A Primer for Programmers Who Lead Programmers&lt;/a&gt;, "If you don't have time to do the job right, when will you have time to do it again?" Delaying refactoring means delaying reaping the benefits of the well-factored code, and working with well-factored code is much easier, and takes much less time than working with poorly factored code. Delaying refactoring could be a huge cost in development time, bugs, performance, and more. Refactoring does not imply that you'll "slip the schedule." It may take you a couple days upfront to do the refactoring (or minutes, or months; it depends) but a good refactoring can save everyone time in the long run because the code will be easier to write, read, debug, understand, extend, maintain, etc.&lt;br /&gt;&lt;br /&gt;It's also common to ignore the need to refactor by saying "we'll push that off until R2." Sometimes it may be acceptable (although, "R2" often never comes) to delay a refactoring until the next release; my opinion is that it's not OK to push off fixing fundamental, core architectural problems. Problems in core code can have a devastating effect on the rest of the code. For example, consider a simple word processor application that has a &lt;code&gt;Document&lt;/code&gt; class that conceptually consists of a list of &lt;code&gt;DocumentPage&lt;/code&gt; classes. If &lt;code&gt;Document&lt;/code&gt; doesn't have a &lt;code&gt;getDocumentPages()&lt;/code&gt; method, then all clients of this code may have to implement their own logic to find all the &lt;code&gt;DocumentPage&lt;/code&gt;s for a given &lt;code&gt;Document&lt;/code&gt; instance. Maybe some clients do it right; maybe some do it wrong and create bugs. The best case you can hope for here is that your code &lt;em&gt;only&lt;/em&gt; suffers from the unwanted duplication of code. Perhaps a better alternative would be to put the logic for finding all the &lt;code&gt;DocumentPage&lt;/code&gt;s in one method inside the &lt;code&gt;Document&lt;/code&gt; class itself (and then unit test it!).   &lt;br /&gt;&lt;br /&gt;So, when's it time to refactor? Always. Now. What should you refactor? Anything that needs it. When you see code that needs refactoring, fix it then and there if possible. If it requires a larger change, discuss the refactoring with your team and figure out when it can be done. If you find yourself cursing a certain chunk of code daily, it may just need to be refactored&amp;mdash;do it. Be vigilant with your code. Take pride in your code. Strive to make your code clean, readable, and&lt;br /&gt;&lt;blockquote&gt;... as simple as possible, but no simpler.&lt;/blockquote&gt; &amp;mdash;Albert Einstein.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h2&gt;Use design patterns, but don't abuse them&lt;/h2&gt;&lt;br /&gt;The use of OO design patterns can be surprisingly controversial. Some folks say they don't know design patterns by name, but that they innately use them anyway because they're just that good at coding. Others swear by patterns; they think the &lt;a href="http://en.wikipedia.org/wiki/GOF"&gt;GoF&lt;/a&gt; book is the final word on the subject, and they can even get overly patterns-happy writing a Hello World program. I think somewhere in the middle is the best place to be.&lt;br /&gt;&lt;br /&gt;A design pattern is simply a way of documenting a solution to a problem. Each pattern has a name, collectively forming a vocabulary with which engineers can intelligently discuss these solutions. Design patterns are to object-oriented programming what algorithms are to functional programming: they are named solutions to common problems. It's much clearer to say that you sorted some numbers using heapsort, rather than explaining the whole heapsort algorithm in detail. Any worthwhile engineer would know what you're talking about. Similarly, it's clearer to say that NSAttributedString is a Decorator, or that NSNotificationCenter implements the Observer pattern, than it is to actually explain how they're implemented. The patterns vocabulary conveys a lot of information in just a few words; it's succinct.&lt;br /&gt;&lt;br /&gt;As we learned from Spider&amp;ndash;Man, with great power comes great responsibility. Just because we know of a pattern doesn't mean we should use it. One of the most misused patterns is the Singleton. The Singleton is probably the easiest of the classic GoF design patterns to understand, which may be why engineers who are new to design patterns abuse it. I already discussed the issues with Singletons in a previous post (&lt;a href="http://unixjunkie.blogspot.com/2006/07/singleton-smell_25.html"&gt;The Singleton Smell&lt;/a&gt;), so I won't go into it all here. But in a nutshell: Singletons are effectively global variables&amp;mdash;avoid them as such, they make for code that's tightly coupled and difficult to test, they limit the reusability of the code, they can cause threading problems, etc. When I see code with lots of Singletons I immediately try to think of ways to refactor the Singletons away. Now, before you flame me saying how much you love and need your Singletons, let me just say that they *can* actually serve a purpose. Although, really, I only know of a few classes that actually should be Singletons.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;h2&gt;Unit test your code&lt;/h2&gt;&lt;br /&gt;Some engineers think of unit testing as an annoying administrative task much like adding a new cover sheet to your TPS report. But the reality is that unit tests are a great benefit to the engineer. They give you confidence that your code is correct. Good code must be semantically correct and do what it claims to do. Unit tests allow you to verify this by formalizing a test case in code that can&amp;mdash;and should&amp;mdash;be run often. If you have a method that claims to accept &lt;code&gt;NULL&lt;/code&gt; as an argument, but you never pass it a &lt;code&gt;NULL&lt;/code&gt;, how do you know it works when passed a &lt;code&gt;NULL&lt;/code&gt;? &lt;br /&gt;&lt;br /&gt;Unit tests are also useful because they allow you to act as the client of the class and can often expose a clumsy API or code that may need refactoring. Once you realize the class needs to be refactored, the unit test will give you confidence that you didn't break anything while refactoring. If you find that your code is very difficult to unit test, then it probably needs to be refactored. If you can't figure out how to use and test your own class, how can you expect anyone else to either? Classes that are difficult to unit test are often so because they don't have a well-defined role or responsibility; don't build "kitchen sink" classes that have way too much responsibility.&lt;br /&gt;&lt;br /&gt;Unit tests are supposed to test the smallest "unit" of an application. This unit may be a command line program, a function, or the usual for an object-oriented program: a class. Don't try to write a unit test that tests your entire application from end-to-end; that's not a unit test. A class should have a clear role and responsibility and the unit test should ensure this.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Read a lot! Spend time keeping up with current technologies, methodologies, design ideas, etc. What you know today may be irrelevant tomorrow. Don't be that grumpy guy who's learned all he's going to and is content with his current state of knowledge. There are a lot of smart people in this industry; learn from them. When you learn something new and cool, share it with others. I'm sure your teammates would appreciate a new trick that will make their lives easier. And, if you're ever in need of that new trick to show off, read up on ssh port forwarding&amp;mdash;that's always a crowd favorite.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/-ENkSTC-ruY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/1025636824095589544/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=1025636824095589544" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1025636824095589544?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1025636824095589544?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/-ENkSTC-ruY/values-of-software-engineer.html" title="Values of a Software Engineer" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/07/values-of-software-engineer.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcBQ3o8eyp7ImA9WB5SGUs.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-2869487419452871917</id><published>2007-06-15T21:21:00.000-07:00</published><updated>2007-06-15T21:27:32.473-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-06-15T21:27:32.473-07:00</app:edited><title>It's official</title><content type="html">Mac OS X 10.5 Leopard on Intel-based Macintosh computers is &lt;a href="http://www.opengroup.org/openbrand/register/brand3555.htm"&gt;certified UNIX&lt;/a&gt; according to the Open Group's &lt;a href="http://www.opengroup.org/openbrand/register/xym0.htm"&gt;Unix 03&lt;/a&gt; standard.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/I4tX7IXRSVI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/2869487419452871917/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=2869487419452871917" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2869487419452871917?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/2869487419452871917?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/I4tX7IXRSVI/its-official.html" title="It's official" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/06/its-official.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04BRX0_fip7ImA9WB5SFE4.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-6446255175840052583</id><published>2007-06-09T16:23:00.000-07:00</published><updated>2007-06-09T16:32:34.346-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-06-09T16:32:34.346-07:00</app:edited><title>WWDC '07</title><content type="html">I'm looking forward to WWDC this year. I think all the Leopard features they've announced so far are cool (particularly DTrace), but I hope the "top secret" Leopard features are even cooler; I really want some super-slick new eye candy. Although, at this point, I'm WAY more excited for the iPhone :-)&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/zqFYl-eaL9s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/6446255175840052583/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=6446255175840052583" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6446255175840052583?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6446255175840052583?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/zqFYl-eaL9s/wwdc-07.html" title="WWDC '07" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/06/wwdc-07.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAARHc8eip7ImA9WBFbGEk.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-1462051631576137208</id><published>2007-05-10T15:47:00.000-07:00</published><updated>2007-05-10T17:35:45.972-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-05-10T17:35:45.972-07:00</app:edited><title>Snagdar Lives!</title><content type="html">A long time ago I wrote a little script called &lt;a href="http://unixjunkie.blogspot.com/2006/05/fetching-darwin-source-simple-way.html"&gt;snagdar.sh&lt;/a&gt; that simplified fetching Darwin source.  It broke when Open Darwin went away and Apple started requiring your ADC login to download some sources.  &lt;br /&gt;&lt;br /&gt;I finally got around to updating the script so that it now works with the current Darwin source at &lt;a href="http://www.opensource.apple.com/darwinsource/"&gt;http://www.opensource.apple.com/darwinsource/&lt;/a&gt;.  However, since it now requires your ADC login name and password, you must create a &lt;code&gt;~/.snagdarpass&lt;/code&gt; file with this information.  &lt;br /&gt;&lt;br /&gt;Let's see how it works from scratch.  We first need to get snagdar.sh.  You can download it from &lt;a href="http://homepage.mac.com/unixjunkie/snagdar.sh"&gt;here&lt;/a&gt;, or you can get it by doing the following.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;curl -s http://homepage.mac.com/unixjunkie/snagdar.sh &amp;gt; snagdar.sh&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;chmod +x snagdar.sh&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now let's use it to get the source for the kernel.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;./snagdar.sh xnu&lt;/b&gt;&lt;br /&gt;./snagdar.sh: line 46: /Users/jgm/.snagdarpass: No such file or directory&lt;br /&gt;ERROR: no username and password found&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yikes!  Oh, right, snagdar now needs a valid ADC login and password so we need to add them to the file &lt;code&gt;~/.snagdarpass&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;echo "username=&lt;i&gt;someone&lt;/i&gt;" &amp;gt; ~/.snagdarpass&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;echo "password=&lt;i&gt;something&lt;/i&gt;" &amp;gt;&amp;gt; ~/.snagdarpass&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;chmod 0600 ~/.snagdarpass&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we should be able to fetch all the source we want.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;./snagdar.sh xnu&lt;/b&gt;&lt;br /&gt;&lt;br /&gt; +++++ Snagging http://www.opensource.apple.com/darwinsource/tarballs/apsl/xnu-792.18.15.tar.gz&lt;br /&gt;  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current&lt;br /&gt;                                 Dload  Upload   Total   Spent    Left  Speed&lt;br /&gt;100 6609k  100 6609k    0     0  1588k      0  0:00:04  0:00:04 --:--:-- 2581k&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And if you want to fetch &lt;em&gt;all&lt;/em&gt; the Darwin sources, you can tell snagdar to fetch the regular expression &lt;code&gt;.&lt;/code&gt;, as in the following example.&lt;br /&gt;&lt;pre&gt;$ &lt;b&gt;./snagdar.sh .&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's pretty much it.  See &lt;a href="http://unixjunkie.blogspot.com/2006/05/fetching-darwin-source-simple-way.html"&gt;the original post&lt;/a&gt; for more details.&lt;br /&gt;&lt;br /&gt;Also, thanks to weltonch777's post at &lt;a href="http://forums.macosxhints.com/archive/index.php/t-50441.html"&gt;http://forums.macosxhints.com/archive/index.php/t-50441.html&lt;/a&gt; for showing how to authenticate with Apple and store the cookie file using curl.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/RTmaftfF-FE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/1462051631576137208/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=1462051631576137208" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1462051631576137208?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1462051631576137208?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/RTmaftfF-FE/snagdar-lives.html" title="Snagdar Lives!" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/05/snagdar-lives.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UHQHg4fCp7ImA9WBFUF08.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-4630310265955821416</id><published>2007-04-27T17:43:00.000-07:00</published><updated>2007-04-27T17:47:11.634-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-04-27T17:47:11.634-07:00</app:edited><title>Fixed Gcalc</title><content type="html">The &lt;a href="http://unixjunkie.blogspot.com/2006/10/google-calculator-from-command-line.html"&gt;command line Google Calculator&lt;/a&gt; that I posted a while ago broke recently when Google changed the HTML on a page.  However, the new HTML has div tag around the calculator answer, so it's now much easier to parse.&lt;br /&gt;&lt;br /&gt;Anyway, the source and project files for the new gcalc can be downloaded from the &lt;a href="http://unixjunkie.blogspot.com/2006/10/google-calculator-from-command-line.html"&gt;original post&lt;/a&gt;.  Or if you have the source yourself, the new XPath for the answer is &lt;code&gt;.//div[@id='res']/table[1]/tr[1]/td[3]/font/b&lt;/code&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/RW_BMhRZghg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/4630310265955821416/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=4630310265955821416" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/4630310265955821416?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/4630310265955821416?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/RW_BMhRZghg/fixed-gcalc.html" title="Fixed Gcalc" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/04/fixed-gcalc.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0EGSX86cCp7ImA9WBFXEUQ.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-7106396725787885130</id><published>2007-03-09T21:58:00.000-08:00</published><updated>2007-03-17T21:20:28.118-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-03-17T21:20:28.118-07:00</app:edited><title>User 99, Unknown</title><content type="html">Most of us are familiar with typical user accounts associated with Unix systems, such as root, nobody, and daemon.  Mac OS X has an additional interesting account for a user named "unknown".  Unknown has the UID number 99, which is treated specially within the kernel as well as some user-level libraries.  The special properties afforded to unknown are needed to make device sharing between computers as painless as possible.  Let us look at what makes unknown so special.&lt;br /&gt;&lt;br /&gt;User unknown, or more precisely, the user with a UID of 99 (we will use "user unknown" or "user 99" interchangeably throughout this document), is treated specially in the following ways:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;  &lt;li&gt;A file owned by UID 99, &lt;em&gt;appears&lt;/em&gt; to be owned by whoever is viewing it (see the caveat immediately following)&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Volumes mounted with the &lt;code&gt;MNT_IGNORE_OWNERSHIP&lt;/code&gt; flag treat all files as if they were owned by UID 99&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;An important caveat to the first bullet above is that this special treatment does not apply to root.  If root views a file owned by unknown, the file appears as it actually is&amp;mdash;owned by user 99.  Let us look at an example.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ &lt;b&gt;touch file.txt&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;ls -l file.txt&lt;/b&gt;&lt;br /&gt;-rw-r--r--   1 jgm  jgm  0 Mar  9 22:07 file.txt&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;sudo chown 99:99 file.txt&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;ls -l file.txt&lt;/b&gt;&lt;br /&gt;-rw-r--r--   1 &lt;em&gt;jgm  jgm&lt;/em&gt;  0 Mar  9 22:07 file.txt&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;sudo ls -l file.txt&lt;/b&gt;&lt;br /&gt;-rw-r--r--   1 &lt;em&gt;unknown  unknown&lt;/em&gt;  0 Mar  9 22:07 file.txt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can see here that I created the file &lt;code&gt;file.txt&lt;/code&gt;, changed its owner and group to 99, but the file continues to show that I own it.  However, if I use &lt;code&gt;sudo&lt;/code&gt; to list the file as root, then we can see that the real owner of the file is indeed unknown.  Further, we can verify the behavior when we list the file as another, non-root user.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ &lt;b&gt;sudo -u &lt;em&gt;test&lt;/em&gt; ls -l file.txt&lt;/b&gt;&lt;br /&gt;-rw-r--r--   1 &lt;em&gt;test  test&lt;/em&gt;  0 Mar  9 22:07 file.txt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This special treatment is handled in the VFS layer of the kernel, specifically, in the file &lt;a href="http://www.google.com/codesearch?hl=en&amp;q=+kpi_vfs+MNT_IGNORE_OWNERSHIP+show:4CSAhwSthoU:0bnv6-sP7n4:wUQy2ud1xwM&amp;sa=N&amp;cd=1&amp;ct=rc&amp;cs_p=http://darwinsource.opendarwin.org/tarballs/apsl/xnu-792.6.61.tar.gz&amp;cs_f=xnu-792.6.61/bsd/vfs/kpi_vfs.c#a0"&gt;&lt;code&gt;xnu/bsd/vfs/kpi_vfs.c&lt;/code&gt;&lt;/a&gt;.  In that file, the &lt;code&gt;vnode_getattr()&lt;/code&gt; function has logic that looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int&lt;br /&gt;vnode_getattr(...) {&lt;br /&gt;  ...&lt;br /&gt;&lt;br /&gt;  if ((nuid == 99) &amp;&amp; !vfs_context_issuser(ctx))&lt;br /&gt;    nuid = kauth_cred_getuid(vfs_context_ucred(ctx));&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This shows the logic used when retrieving the attributes of a vnode (basically, a vnode is an in-kernel structure that representats a file).  We see that if the vnode is owned by UID 99, and the current calling process is &lt;em&gt;not&lt;/em&gt; root, then change the vnode's UID to that of the calling process.  The equivalent logic for handling a GID of 99 is not shown here.  This is exactly the behavior that was demonstrated above.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The second special property of user unknown mentioned above was that volumes mounted with the &lt;code&gt;MNT_IGNORE_OWNERSHIP&lt;/code&gt; flag cause all files to appear as if they were owned by user unknown.  Additionally, new files will be created with an owner and group of unknown.  In many cases, the &lt;code&gt;MNT_IGNORE_OWNERSHIP&lt;/code&gt; flag can be controlled on a per-volume basis by checking the "Ignore ownership on this volume" checkbox in the volume's "Get Info" Finder window.  However, it can also be set by specifying &lt;code&gt;MNT_IGNORE_OWNERSHIP&lt;/code&gt; when calling &lt;code&gt;mount(2)&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;We can determine whether or not a volume has this flag set by using the following C program.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ &lt;b&gt;cat mnt_ownership.c&lt;/b&gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/param.h&amp;gt;&lt;br /&gt;#include &amp;lt;sys/mount.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int&lt;br /&gt;main(int argc, char **argv) {&lt;br /&gt;  struct statfs sb;&lt;br /&gt;  int ignore_flag;&lt;br /&gt;&lt;br /&gt;  /* argv[1] is path to the volume or a file/folder within */&lt;br /&gt;  statfs(argv[1], &amp;sb);&lt;br /&gt;  ignore_flag = (sb.f_flags &amp; MNT_IGNORE_OWNERSHIP);&lt;br /&gt;  printf("ownership %s\n", ignore_flag ?  "ignored" : "enabled");&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;gcc -o mnt_ownership mnt_ownership.c -Wall&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;./mnt_ownership /Volumes/TINY&lt;/b&gt;&lt;br /&gt;ownership ignored&lt;br /&gt;&lt;/pre&gt; &lt;br /&gt;&lt;br /&gt;We can see here that the mounted volume for my iPod shuffle is ignoring ownership.  This means that all files on the iPod should appear to be owned by me (or whomever, depending on the rules discussed above), and files created on the iPod should be created as user 99.  Let us look at an example.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ &lt;b&gt;cd /Volumes/TINY&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;ls -l&lt;/b&gt;&lt;br /&gt;total 16&lt;br /&gt;drwxrwxrwx   1 jgm  jgm  8192 Jan 27 14:12 iPod_Control/&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;sudo ls -l&lt;/b&gt;&lt;br /&gt;total 16&lt;br /&gt;drwxrwxrwx   1 unknown  unknown   8192 Jan 27 14:12 iPod_Control&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;touch file.txt&lt;/b&gt;&lt;br /&gt;$ &lt;b&gt;ls -l file.txt &lt;/b&gt;&lt;br /&gt;-rwxrwxrwx   1 jgm  jgm  0 Mar 10 16:27 file.txt&lt;br /&gt;&lt;br /&gt;$ &lt;b&gt;sudo ls -l file.txt&lt;/b&gt;&lt;br /&gt;-rwxrwxrwx   1 unknown  unknown  0 Mar 10 16:27 file.txt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This special behavior is also handled in the VFS layer of the kernel&amp;mdash;it's actually handled about 5 lines above the &lt;code&gt;vnode_getattr()&lt;/code&gt; snippet discussed above.  The relevant code from the function is highlighted here.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int&lt;br /&gt;vnode_getattr(...) {&lt;br /&gt;  ...&lt;br /&gt;  &lt;b&gt;/*&lt;br /&gt;   * Handle uid/gid == 99 and MNT_IGNORE_OWNERSHIP here.&lt;br /&gt;   */&lt;br /&gt;  ...&lt;br /&gt;  if (vp-&gt;v_mount-&gt;mnt_flag &amp; MNT_IGNORE_OWNERSHIP) {&lt;br /&gt;    nuid = vp-&gt;v_mount-&gt;mnt_fsowner;&lt;br /&gt;    if (nuid == KAUTH_UID_NONE)&lt;br /&gt;      nuid = 99; &lt;br /&gt;    ...&lt;br /&gt;  }&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;  if ((nuid == 99) &amp;&amp; !vfs_context_issuser(ctx))&lt;br /&gt;    nuid = kauth_cred_getuid(vfs_context_ucred(ctx));&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We see that if the MNT_IGNORE_OWNERSHIP flag is specified, the &lt;code&gt;mnt_fsowner&lt;/code&gt; value of the mounted file system is consulted.  If that value is &lt;code&gt;KAUTH_UID_NONE&lt;/code&gt;, then the kernel hardcodes a value of 99&amp;mdash;user unknown.  Following that, we go through the same logic as before for handling files owned by 99.&lt;br /&gt;&lt;br /&gt;One question this brings up is, what if the &lt;code&gt;mnt_fsowner&lt;/code&gt; value is &lt;em&gt;not&lt;/em&gt; &lt;code&gt;KAUTH_UID_NONE&lt;/code&gt;?  In that case, the files on the volume will appear to be owned by the user specified in &lt;code&gt;mnt_fsowner&lt;/code&gt;.  In the kernel, HFS+ is the only file system that actually makes use of this feature.  This fact is actually commented in several places with &lt;code&gt;/* XXX 3762912 hack to support HFS filesystem 'owner' */&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Common Questions and Answers&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Does this mean that all users can see files owned by user 99?&lt;br /&gt;&lt;br /&gt;No.  There is more than simply ownership involved in deciding whether or not you can view a file.  For example, if the mode of a file that you own is &lt;code&gt;000&lt;/code&gt;, then you will not be able to read that file.  Furthermore, if you are denied access to any directory in a file's path, you will be unable to read it.  These are just a few of the reasons why this answer is "no".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Is user 99 only given this special treatment on volumes mounted with MNT_IGNORE_OWNERSHIP?&lt;br /&gt;&lt;br /&gt;No.  User 99 is treated the same on all volumes mounted under Mac OS X.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Why was this stuff done?&lt;br /&gt;&lt;br /&gt;The folks at Apple would know for sure, however, I assume it was added to simplify the sharing of devices (e.g., thumb drives and iPods) among computers.  If this were not done, then your real UID would be consulted when determining your access to a file.  And the fact that your UID may differ on different computers could make this whole process troublesome.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Should I uncheck "Ignore ownership on this volume" on my devices?&lt;br /&gt;&lt;br /&gt;Maybe.  If the device is shared among several computers, like an iPod or a thumb drive, then you probably want to leave that box checked (see the answer to the previous question).  However, if you have a 500GB external drive that you always leave attached to one machine, then unchecking that box is probably a good idea.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In the first paragraph, you mention that some user-level libraries treat user 99 specially.  What are you referring to?&lt;br /&gt;&lt;br /&gt;UPDATE: Some Carbon APIs do return incorrect information when displaying metadata about files owned by "unknown" to a root process&amp;mdash;they show root as owning the file, when they should report it as user 99.  This issue may be in the Carbon framework itself, or in the system calls used to retrieve the information (I haven't looked into it).&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/7EUgsfnuGAY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/7106396725787885130/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=7106396725787885130" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/7106396725787885130?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/7106396725787885130?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/7EUgsfnuGAY/user-99-unknown.html" title="User 99, Unknown" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>11</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/03/user-99-unknown.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMFRn48fCp7ImA9WBFRFUk.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-6576021783553875025</id><published>2007-02-26T17:36:00.000-08:00</published><updated>2007-02-26T17:40:17.074-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-26T17:40:17.074-08:00</app:edited><title>SpotlightFS Source Available</title><content type="html">Some folks were asking me about this, and I'm sorry I couldn't answer sooner.  Anyway, the source for SpotlightFS is now available via the main &lt;a href="http://code.google.com/p/macfuse/"&gt;MacFUSE&lt;/a&gt; project page.&lt;br /&gt;&lt;br /&gt;Oh, there's also a very cool Objective-C wrapper around MacFUSE that makes writing a file system almost trivial.  The source for this is also available over at &lt;a href="http://code.google.com/p/macfuse/"&gt;MacFUSE&lt;/a&gt;.  Please go check it out.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/vPhnqVwJk64" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/6576021783553875025/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=6576021783553875025" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6576021783553875025?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/6576021783553875025?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/vPhnqVwJk64/spotlightfs-source-available.html" title="SpotlightFS Source Available" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/02/spotlightfs-source-available.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QCQXg5fCp7ImA9WBFSGUg.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-1761407156561943428</id><published>2007-02-19T19:17:00.000-08:00</published><updated>2007-02-19T22:02:40.624-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-19T22:02:40.624-08:00</app:edited><title>Costco's Microsoft iPod Display</title><content type="html">I stopped by &lt;a href="http://www.costco.com/Home.aspx"&gt;Costco&lt;/a&gt; today to see if it was worth a membership.  I was greeted by a lovely iPod display just a few feet inside the door, but something was amiss.  Needless to say, I left sans membership (there were other reasons as well).  &lt;br /&gt;&lt;br /&gt;&lt;img src="http://homepage.mac.com/unixjunkie/pics/MSiPod.jpg" /&gt;&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/LSIhlzGVpT4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/1761407156561943428/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=1761407156561943428" title="13 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1761407156561943428?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1761407156561943428?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/LSIhlzGVpT4/costcos-microsoft-ipod-display.html" title="Costco's Microsoft iPod Display" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>13</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/02/costcos-microsoft-ipod-display.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQHSXs6eCp7ImA9WBFTGU0.&quot;"><id>tag:blogger.com,1999:blog-10602853.post-1536528528669018812</id><published>2007-02-07T19:47:00.000-08:00</published><updated>2007-02-07T20:02:18.510-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2007-02-07T20:02:18.510-08:00</app:edited><title>Switch to zsh</title><content type="html">Hey folks.  I have been working on some pretty neat stuff lately, but I haven't had much time to post.  I'll try to get an interesting post out the door soon.&lt;br /&gt;&lt;br /&gt;I'm also giving zsh a shot as my default shell.  I've always liked bash because it's very powerful and can do some very &lt;a href="http://unixjunkie.blogspot.com/2006/01/two-cool-bash-tricks.html"&gt;cool things&lt;/a&gt;, but zsh seems to have just about everything bash has, and then some.  One of the biggest benefits of zsh is that zsh lets you have a shell prompt on the right-hand side of the screen; really cool.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;moby[jgm]&amp;gt; &lt;b&gt;cd /var/log&lt;/b&gt;                                ~ &lt;br /&gt;moby[jgm]&amp;gt;                                     /var/log&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Most of  the advanced shell tricks, such as &lt;a href="http://unixjunkie.blogspot.com/2006/01/two-cool-bash-tricks.html"&gt;process substitution&lt;/a&gt;, also work in zsh, so you likely won't miss much there.  Zsh can't do the bash trick of creating sockets by referencing files in &lt;code&gt;/dev/tcp/host/port&lt;/code&gt;, but as cool as that is, I never actually found a use for it (&lt;code&gt;nc&lt;/code&gt; is almost always more versatile in this respect).&lt;br /&gt;&lt;br /&gt;So far zsh seems pretty darn cool, and it's an easy switch from any bourne-style shell.&lt;img src="http://feeds.feedburner.com/~r/UnixjunkieBlog/~4/6BCJaERbXB4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://unixjunkie.blogspot.com/feeds/1536528528669018812/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=10602853&amp;postID=1536528528669018812" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1536528528669018812?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/10602853/posts/default/1536528528669018812?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/UnixjunkieBlog/~3/6BCJaERbXB4/switch-to-zsh.html" title="Switch to zsh" /><author><name>Greg</name><uri>http://www.blogger.com/profile/04800931220431582024</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="24" src="http://homepage.mac.com/unixjunkie/me2.jpg" /></author><thr:total>11</thr:total><feedburner:origLink>http://unixjunkie.blogspot.com/2007/02/switch-to-zsh.html</feedburner:origLink></entry></feed>
