<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9636763</id><updated>2012-01-28T00:35:19.883-05:00</updated><category term='ruby'/><category term='linux'/><category term='timehole'/><category term='ldap'/><category term='FiOS'/><category term='iPhone'/><category term='iTunes'/><category term='java'/><category term='unix'/><category term='apple'/><category term='mac'/><category term='programming'/><category term='class'/><category term='os x'/><category term='Ubuntu'/><category term='squeezebox'/><category term='mythtv'/><title type='text'>The Shadow File</title><subtitle type='html'>My notes on technology, security, and personal projects</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9636763.post-7887309068603184049</id><published>2011-12-16T11:01:00.001-05:00</published><updated>2011-12-16T11:05:14.037-05:00</updated><title type='text'>Long-form Reading 2011</title><content type='html'>Here are some long-form articles I've enjoyed this year.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.theatlantic.com/technology/print/2010/12/the-hazards-of-nerd-supremacy-the-case-of-wikileaks/68217/"&gt;The Hazards of Nerd Supremacy: The Case of Wikileaks&lt;/a&gt; (theatlantic.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.wired.com/magazine/2011/02/ff_octopus_conspiracy/all/1"&gt;The Octopus Conspiracy: One Woman's Search for Her Father's Killer&lt;/a&gt; (wired.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.theatlantic.com/magazine/archive/2001/09/confessions-of-a-prep-school-college-counselor/2281/"&gt;Confessions of a Prep School College Counselor&lt;/a&gt; (theatlantic.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://berlinbooks.org/brb/2011/01/the-great-rubber-robbery-how-julius-fromm%E2%80%99s-condom-empire-fell-to-the-nazis/"&gt;The Great Rubber Robbery: How Julius Fromm's Condom Empire Fell to the Nazis&lt;/a&gt; (berlinbooks.org)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.houstonpress.com/content/printVersion/218684/"&gt;Bursting the Bubble&lt;/a&gt; (about David Vetter, the "Bubble Boy", houstonpress.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.slate.com/articles/news_and_politics/assessment/2011/02/the_stutterer.single.html"&gt;The Stutterer: How He Makes His Voice Heard&lt;/a&gt; (slate.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.gq.com/entertainment/movies-and-tv/201102/the-day-the-movies-died-mark-harris?printable=true"&gt;The Day The Movies Died&lt;/a&gt; (gq.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.theatlantic.com/business/print/2011/03/man-vs-machine-on-wall-street-how-computers-beat-the-market/73120/"&gt;Man vs. Machine on Wall Street: How Computers Beat the Market&lt;/a&gt; (theatlantic.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.wired.com/magazine/2011/03/ff_drugsub/all/1"&gt;Authorities in Awe of Drug Runner's Jungle Build, Kevlar-Coated Supersubs&lt;/a&gt; (wired.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.rollingstone.com/culture/news/kiki-kannibal-the-girl-who-played-with-fire-20110415?print=true"&gt;Kiki Kannibal: The Girl Who Played With Fire&lt;/a&gt; (rollingstone.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.tnr.com/print/article/the-battle-tora-bora?page=all,2&amp;amp;passthru=MWVlZjYxNzBiY2E1ZjI3Mzk1MGY3YWZiZjM1ZTgyZDU"&gt;The Battle for Tora Bora&lt;/a&gt; (tnr.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.inc.com/articles/201106/the-humility-imperative-ceos-keep-your-arrogance-in-check.html"&gt;The Humility Imperative: CEOs Keep Your Arrogance in Check&lt;/a&gt; (inc.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.theatlantic.com/magazine/print/2011/07/how-to-land-your-kid-in-therapy/8555/"&gt;How to Land Your Kid in Therapy&lt;/a&gt; (theatlantic.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.wired.com/magazine/2011/07/ff_scammingslots/all/1"&gt;How One Man Hacked His Way Into the Slot-Machine Industry&lt;/a&gt; (wired.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.businessweek.com/printer/magazine/cyber-weapons-the-new-arms-race-07212011.html"&gt;Cyber Weapons: The New Arms Race&lt;/a&gt; (businessweek.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.tnr.com/print/article/books/magazine/91916/google-schmidt-obama-gates-technocrats"&gt;Don't Be Evil&lt;/a&gt; (on google's narrowly conceived, yet handicapping motto, tnr.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.newyorker.com/reporting/2008/05/26/080526fa_fact_acocella?currentPage=all"&gt;A Few Too Many: Is there any hope for the hung over?&lt;/a&gt; (newyorker.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.dallasobserver.com/content/printVersion/2365078/"&gt;The Man With the $16 House&lt;/a&gt; (dallasobserver.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.grantland.com/story/_/id/6891795/the-wrestler-real-life"&gt;The Wrestler in Real Life&lt;/a&gt; (on Ric Flair's long decline, grantland.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.vanityfair.com/culture/fexatures/2011/09/chinese-hacking-201109?printable=true"&gt;Enter the Cyber-dragon&lt;/a&gt; (on how China is operating with impunity on America's defense and commercial computer networks, vanityfair.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.businessweek.com/magazine/apples-supplychain-secret-hoard-lasers-11032011.html"&gt;Apple's Supply Chain Secret? Hoard Lasers&lt;/a&gt; (business week.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://chronicle.com/article/50-Years-of-Stupid-Grammar/25497"&gt;50 Years of Stupid Grammar Advice&lt;/a&gt; (thechronicle.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://thephoenix.com/Boston/music/129722-rise-and-fall-of-the-columbia-house-record-clu/?page=5#TOPCONTENT"&gt;The Rise and Fall of the Columbia House Record Club -- and How We learned to Steal Music&lt;/a&gt; (thephoenix.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.nytimes.com/2011/11/09/business/how-a-financial-pro-lost-his-house.html?_r=1&amp;amp;pagewanted=all"&gt;How a Financial Pro Lost His House&lt;/a&gt; (nytimes.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://nymag.com/print/?/news/politics/conservatives-david-frum-2011-11/"&gt;When Did the GOP Lose Touch With Reality?&lt;/a&gt; (nymag.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.businessweek.com/printer/magazine/what-is-sony-now-11172011.html"&gt;What is Sony Now?&lt;/a&gt; (businessweek.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.businessweek.com/printer/magazine/what-is-sony-now-11172011.html"&gt;The Pest Who Shames Companies Into Fixing Security Flaws&lt;/a&gt; (wired.com)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Thanks to Marco Arment's excellent&amp;nbsp;&lt;a href="http://instapaper.com/"&gt;Instapaper&lt;/a&gt;&amp;nbsp; service and iOS app for helping find and keep track of excellent reading material on the web.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-7887309068603184049?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/7887309068603184049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=7887309068603184049' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7887309068603184049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7887309068603184049'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2011/12/long-form-reading-2011.html' title='Long-form Reading 2011'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5936204554767371045</id><published>2011-12-13T15:15:00.000-05:00</published><updated>2011-12-13T15:15:43.751-05:00</updated><title type='text'>Reading List 2011</title><content type='html'>I was using up all of my accumulated credits on Audible.com just now, and realized I've listened to several great audiobooks over the last year. Here's a list of what I've listened to in 2011, along with a link to the book on Audible.com. I recommend them all.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Judas Unchained&lt;/u&gt;, Peter F. Hamilton, Part 2 of the Commonwealth Saga (&lt;a href="http://www.audible.com/pd?asin=B002V0QZL0"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;The Gun&lt;/u&gt;,&amp;nbsp;C. J. Chivers (&lt;a href="http://www.audible.com/pd?asin=B0045KKG6E"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;The Windup Girl&lt;/u&gt;, Paolo Bacigalupi (&lt;a href="http://www.audible.com/pd?asin=B002UZN4MO"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;Snow Crash&lt;/u&gt;, Neal Stephenson (&lt;a href="http://www.audible.com/pd?asin=B002UUKWCY"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;Embassytown&lt;/u&gt;, China Mieville (&lt;a href="http://www.audible.com/pd?asin=B00500HQNE"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;Pattern Recognition&lt;/u&gt;, William Gibson (&lt;a href="http://www.audible.com/pd?asin=B002V8OCTY"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;Spook Country&lt;/u&gt;, William Gibson (&lt;a href="http://www.audible.com/pd?asin=B002V5GO3O"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;u&gt;Zero History&lt;/u&gt;, William Gibson (&lt;a href="http://www.audible.com/pd?asin=B0040HTAHS"&gt;link&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;I'm pretty excited about my reading list for 2012 (and likely beyond--I had 12 credits to use), which I will share soon.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5936204554767371045?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5936204554767371045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5936204554767371045' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5936204554767371045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5936204554767371045'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2011/12/reading-list-2011.html' title='Reading List 2011'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5300122511337094288</id><published>2011-11-13T19:40:00.002-05:00</published><updated>2011-11-14T08:19:41.329-05:00</updated><title type='text'>Multi-page Javascript Bookmarklet</title><content type='html'>[Disclaimer: I don't know crap about javascript, other than what I pieced together from the 'tubes.]&lt;br /&gt;I read something somewhere (I don't remember where) about having a &lt;a href="http://en.wikipedia.org/wiki/Bookmarklet"&gt;bookmarklet&lt;/a&gt; that automatically opens your favorite sites, each in their own tab, when you click on it. I wanted to set up my own, but the article didn't explain how to do it (just suggested it as an idea). It's actually pretty easy. &amp;nbsp;Below is commented code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;javascript:(function(){&lt;br /&gt;  /* save a reference to the current window */&lt;br /&gt;  oldWin=window;&lt;br /&gt;  &lt;br /&gt;  /*&lt;br /&gt;   * Replace the current window's or tab's website with this one.&lt;br /&gt;   * If you just want additional windows (or tabs) opened&lt;br /&gt;   * skip this.&lt;br /&gt;   */&lt;br /&gt;  location.href='https://mail.google.com';&lt;br /&gt;  &lt;br /&gt;  /* Each additional window/tab you want opened */&lt;br /&gt;  window.open('https://voice.google.com');&lt;br /&gt;  window.open('http://www.accuweather.com');&lt;br /&gt;   &lt;br /&gt;  /* restore focus to the original tab, since each&lt;br /&gt;   * new window gets focus&lt;br /&gt;   */&lt;br /&gt;  oldWin.focus();&lt;br /&gt;})();&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Paste this entire javascript fragment in as the address for your bookmark.  It may be easier to bookmark an arbitrary page, then edit that bookmark's title and address.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5300122511337094288?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5300122511337094288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5300122511337094288' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5300122511337094288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5300122511337094288'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2011/11/make-multi-page-bookmarklet.html' title='Multi-page Javascript Bookmarklet'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5558742970408100080</id><published>2011-11-04T07:14:00.012-04:00</published><updated>2011-11-04T15:13:54.704-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>On the Mac App Store and Sandbox Restrictions</title><content type='html'>&lt;div&gt;&lt;b&gt;Update&lt;/b&gt;: My friend, Chad, creator of &lt;a href="http://www.usefulfruit.com/"&gt;Pear Note&lt;/a&gt;, has an interesting &lt;a href="http://www.c-had.com/app-store-sandboxing"&gt;perspective&lt;/a&gt; that is much more in-depth than what I have written.  While I don't agree with his conclusion, he is a successful full-time Mac developer where I have no Mac development experience.  Also Chad has more SELinux background that I do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;There has been a lot of &lt;a href="http://lacquer.fi/pauli/blog/2011/11/why-the-mac-app-sandbox-makes-me-sad/"&gt;gnashing of teeth&lt;/a&gt; lately over Apple's forthcoming Sandbox restrictions on software sold through the Mac App Store.  In the near future, applications sold through the Mac App Store will be confined by very restrictive security policies.  These security policies will make it impossible for applications to do many of the things we are accustomed to applications being able to do, such as interact with other applications.  Some have described this change, pejoratively, as the "iOS-ification" of the Mac.  I think these people miss some important points.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I used to work at a company where most of my time involved developing either SELinux security policies (a technical mechanism that the operating system uses to restrict applications' behavior) or applications designed to be confined by SELinux policies.  Unfortunately, although SELinux is extremely powerful, it isn't used to confine most Linux desktop applications.  It exposes users to problems that are beyond their ability (or desire) to troubleshoot and fix. Having spent time working with under-appreciated access control mechanisms, I am really excited to see Sandboxes coming into the mainstream on an operating system known for its ease of use.  This is a Good Thing for users.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SELinux is similar in some ways to Mac OS X's (and iOS's) Sandbox mechanism.  These mechanisms enforce a system-wide security policy that cannot be overridden through traditional user-based file ownership and permissions.  For example, an application executed by you shouldn't be allowed to change or delete all of your data (without asking you first) simply because you own the data.  An unconfined application could be tricked into doing just that.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Apple has implemented a &lt;a href="http://arstechnica.com/apple/reviews/2011/07/mac-os-x-10-7.ars/9"&gt;trusted process model&lt;/a&gt; in OS X Lion to handle risky behaviors. An application confined by a Sandbox profile might not be allowed to write its data to your hard disk.  Instead, it has to send its data to a Lion-provided process whose job it is to write the data.  That trusted process is &lt;i&gt;only&lt;/i&gt; allowed to access data on the hard disk. It &lt;i&gt;is not&lt;/i&gt; allowed to receive connections from other computers on the Internet.  An attacker on the Internet would have to compromise not only your application, but also the trusted process in order to gain access to your data on your hard disk.  Think of  a building that requires entry through one door followed by another, and no single person has both keys.  You have to co-opt both key holders to gain access.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Many things that applications normally do on their own will now have to be proxied through a trusted interface provided by Lion.  Some things, such as adding cover art to iTunes albums, become impossible where no sanctioned interface is provided.  In the near term, applications in the Mac App Store will become simpler and less capable because of this.  I suspect that over time, though, Apple will provide more robust set of mechanisms that applications will be able to use to do more things.  This way, applications will be able to do more on behalf of the user without introducing significant risk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I like knowing that applications I install through the Mac App Store will be confined by a security mechanism that mitigates mistakes made by the developer.  I'm happy with it as long as I can obtain applications from outside the App Store when I'm willing to assume more risk.  You have choices.  If you want an application that not only &lt;i&gt;won't&lt;/i&gt; but &lt;i&gt;can't&lt;/i&gt; eat your data (or syphon it off to the Russian mafia) get it from the Mac App Store.  If you want an application that has more features--and more risk--buy it &lt;strike&gt;elsewhere&lt;/strike&gt; from Chad's &lt;a href="http://www.usefulfruit.com"&gt;website&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5558742970408100080?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5558742970408100080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5558742970408100080' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5558742970408100080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5558742970408100080'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2011/11/on-mac-app-store-and-sandbox.html' title='On the Mac App Store and Sandbox Restrictions'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-3389593760573546276</id><published>2010-12-19T10:43:00.006-05:00</published><updated>2010-12-19T13:11:33.625-05:00</updated><title type='text'>Fake Reviews on Amazon?</title><content type='html'>We all know there are shady marketing/image promotion firms that do things like post fake reviews on Amazon.com and others.  However, I've never actually &lt;i&gt;seen&lt;/i&gt; a review that I was certain was a fake.  That is, before today.&lt;br /&gt;&lt;br /&gt;Yesterday I bought a no-name 21 bottle thermo-electric wine cooler from Tuesday Morning.  I wanted a feel for whether I got a good deal, so I did some post-purchase comparison shopping on Amazon.com.  I couldn't find my exact model there.  Again, I'm certain it's a no-name, made-in-china, rebranded by a distributor type affair.  I did find a couple of models on Amazon that are extremely similar to my own. So much so that I would not be surprised if they are actually the same unit with minor cosmetic revisions.&lt;br /&gt;&lt;br /&gt;As I was reading the customer reviews, they were mostly pretty terrible, complaining of failures within 18 months of purchase.  Most also complained that there wasn't a place locally to get the appliance serviced. Unsurprising.  Oh, well. Live and learn, I guess :-(.&lt;br /&gt;&lt;br /&gt;However, what was interesting to me was that for each  of the two items, I found one review that was uncharacteristically positive.  Even less likely, both reviews were impossibly similar, following a template, highlighting the same positive features, and using similar wording.  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm not going to link to the Amazon product listing because I don't want to help boost those items' page ranking, but I have pasted in the product name as found on Amazon, as well as the full review in each case.&lt;br /&gt;&lt;br /&gt;From the "NewAir AW-210ED NewAir Thermoelectric Wine Cooler With Dual Temperature Zones"&lt;br /&gt;&lt;div&gt;A four star review:&lt;/div&gt;&lt;br /&gt;&lt;blockquote&gt;I ordered this as a present for my wife, and read a lot of reviews. There were so many negative product reviews for wine coolers, I really didn't know which one was actually the truth. I didn't know what to buy or who to believe.&lt;br /&gt;&lt;br /&gt;This fridge is really quiet. In an empty room without any other appliances on, you can't hear it.&lt;br /&gt;&lt;br /&gt;It's beautiful. It's aesthetically pleasing and fits in well into our dining room. She loves the sleek black finish, we get lots of compliments on it. It gets a lot of attention believe it or not. Some people are really impressed by it. My friends think NewAir should of made room for cans of Bud Light, but I disagree. The unit stores my $[...]bottles of Opus One. It is definitely a higher end unit meant to store wine collections not beer for UFC fights. Same high quality as Cuisinart models we've seen at Bloomingdales, but bigger which means more room for WINE! I would definitely choose this unit over a built in unit. This model requires some room for venting like most refrigerators, which makes sense. We had a built in wine cooler in our last house and it was nothing but problems. When they had to fix because the compressor went I had to contact a laundry list of people because the manufacturer went out of business. Then the guy who came to fix it decided it was ok to damage our granite bar top to access the built in wine cooler.&lt;br /&gt;&lt;br /&gt;No assembly except putting on the handle. Let's face it not many of us spoiled Southern Californians are handy.&lt;br /&gt;&lt;br /&gt;he temperature holds steady and does not reset when exposed to sunlight, or when the room is warm. It's really easy to read the temp setting, really easy to set, and it works like a dream. The LED lighting is awesome. Also, you can feel the difference in temperature between the 2 zones.&lt;br /&gt;&lt;br /&gt;Dollar for dollar, this was competitively priced. I really liked my experience with Air &amp;amp; Water. They were great. And, we're SO happy with it.&lt;br /&gt;&lt;br /&gt;I know you will be too.&lt;/blockquote&gt;And from the EdgeStar 21 Bottle Dual Zone Wine Cooler&lt;br /&gt;&lt;div&gt;A five star review:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;blockquote&gt;I ordered this as a present, and read a lot of reviews. There are so many negative product reviews for wine fridges, I really didn't know what to buy. So, let me put your fears to rest:&lt;br /&gt;&lt;br /&gt;1) This fridge is really quiet. In an empty room with no AC on, you can't hear it.&lt;br /&gt;&lt;br /&gt;2) It's beautiful. Really nice stainless finish, we get lots of compliments on it. On par with Cuisinart models we've seen at Macy's, but bigger.&lt;br /&gt;&lt;br /&gt;3) No assembly except putting on the handle. Hallelujah!!!&lt;br /&gt;&lt;br /&gt;4) Consistent temperature - the temp holds steady and does not reset when exposed to sunlight, or when the room is warm. It's really easy to read the temp setting, really easy to set, and it works like a dream. You can feel the difference in temperature between the 2 zones.&lt;br /&gt;&lt;br /&gt;Dollar for dollar, this was competitively priced. I really liked my interaction with Compact Appliance. They were great. And, we're SO happy with it.&lt;br /&gt;&lt;br /&gt;Hope you will be too.&lt;/blockquote&gt;Here are the points addressed by each review, in the same order:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;The unit is quiet, and in a quiet room, you can't hear it&lt;/li&gt;&lt;li&gt;The unit is beautiful&lt;/li&gt;&lt;li&gt;Requires little to no assembly&lt;/li&gt;&lt;li&gt;Keeps a consistent temperature&lt;/li&gt;&lt;li&gt;Competitively priced&lt;/li&gt;&lt;li&gt;Interaction with the manufacturer/distributor was great (WTF? you bought it from Amazon.com)&lt;/li&gt;&lt;li&gt;We're &lt;b&gt;so&lt;/b&gt; happy and "hope you will be too."&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's kind of amazing how blatant these reviews are.  I guess the most Amazon can do is close each user's account.  Since the reviewers are disposable, the PR firm just hires more, or even creates new accounts under new names.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-3389593760573546276?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/3389593760573546276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=3389593760573546276' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3389593760573546276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3389593760573546276'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2010/12/fake-reviews-on-amazon.html' title='Fake Reviews on Amazon?'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-2072825454302393601</id><published>2010-05-01T12:10:00.005-04:00</published><updated>2010-05-01T21:31:02.041-04:00</updated><title type='text'>Remarks on Apple, Flash and the "I Hate Apple" People</title><content type='html'>I've want to put down in words a few loosely related thoughts on controversy regarding Apple's policy of not allowing Adobe Flash Player on its mobile devices, and on the &lt;span style="font-style:italic;"&gt;I Hate Apple&lt;/span&gt; crowd in general.&lt;br /&gt;&lt;br /&gt;First, the "I'm anti-apple" people.  I hear this mantra repeated frequently by friends and colleagues and also by noisy people on the Internet.  I tend to rail against this sort of thinking, and as a result, come off as an Apple apologist to people who know me.  I'll clarify: there are plenty of legitimate reasons to be angry with Apple.  This vitriol, however, just seems irrational.  Apple, as a company, has a lot of surface area and characterizing them in such broad strokes is problematic.  They do things that are frustrating, but they also do things that are great.  Most people who revel in waving their Apple-hating flag struggle to articulate just why they they hate them so much.  It usually goes something like "grumble grumble, closed, proprietary, grumble grumble, App Store, grumble, no flash on the iPhone." The argument usually doesn't hold together well, and often these people will even admit that they just can't quite put their finger on what they hate so much about Apple.  Look, we all are frustrated with Apple's App Store policies, even veteran iPhone and Mac developers.  Even John Gruber, often accused of being an apologist is frustrated:&lt;br /&gt;&lt;a href="http://daringfireball.net/linked/2009/07/18/marco-doubts"&gt;Serious App Store Doubts&lt;/a&gt;&lt;br /&gt;&lt;a href="http://daringfireball.net/2009/05/diary_of_an_app_store_reviewer"&gt;Excerpts From the Diary of an App Store Reviewer&lt;/a&gt;&lt;br /&gt;&lt;a href="http://daringfireball.net/2008/09/app_store_exclusion"&gt;The App Store’s Exclusionary Policies&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Further, if we're going to jump on the Apple-hating bandwagon, which is very in vogue nowadays, there are a lot of big-company-hating bandwagons we're going to have to jump on and start bitching about and boycotting.  That's tiring. I don't have enough hours in the day to hate every company that needs hating.  Sigh.  Pick your battles.&lt;br /&gt;&lt;br /&gt;Moving on to Apple's prohibition of Adobe Flash Player.  It's not that complicated.  Flash on the iPhone specifically, and cross-platform development frameworks in general, have the effect of diluting all platforms, including the iPhone, down to the lowest common set of platform features.  No company should want their mobile device to be reduced to a state of generic similarity to their competitors' devices.  Apple is perfectly justified, in my opinion, in wanting to keep this sort of shovel-ware out of the App Store.&lt;br /&gt;This week Apple CEO Steve Jobs penned an open letter regarding his company's position on Adobe Flash Player on the iPhone OS:&lt;br /&gt;&lt;a href="http://www.apple.com/hotnews/thoughts-on-flash/"&gt;Thoughts on Flash&lt;/a&gt;&lt;br /&gt;I won't dissect the letter; it's been covered.  But I agree with everything in it.&lt;br /&gt;&lt;br /&gt;In response, this blustery counterpoint was posted on Linux-Magazine.com:&lt;br /&gt;&lt;a href="http://www.linux-magazine.com/Online/Blogs/Beagleblog/Apple-s-Steve-Jobs-is-spreading-FUD-on-Flash"&gt;Apple's Steve Jobs is spreading FUD on Flash&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This author's post actually makes me angry.  It makes me angry because he is so bigoted against Apple, that he actually comes to Adobe's defense, conveniently forgetting that they've been dragging down the Linux desktop experience for years.&lt;br /&gt;&lt;br /&gt;I self-identify as both a a Mac user and a Linux user.  For years I was a full-time Linux user.  I was the most obnoxious of Linux bigots, so I have that perspective.  I have unhappy memories of flash on Linux. Since flash video became prevalent on the Internet, Adobe flash player has been the bane of Linux users' existence.  Its performance on Linux has always been abysmal. I remember times when my laptop's fans would spin up to full speed, and the battery would start draining, and it would start scorching my lap.  I would have to go hunt down whatever Firefox tab had a flash-based banner ad that was eating my CPU for lunch.  &lt;br /&gt;&lt;br /&gt;Adobe was slow to update it to the latest release, taking a year or more after it was released on Windows to release a new version for Linux.  Also, Adobe still hasn't released a 64-bit version of the Flash Player for Linux or the Mac.  Yeah. Seriously.  It's 2010.  Although major Linux distributions have gotten a lot better at making flash installation easy, you used to have to do weird 32-bit library wrapping voodoo to get Adobe Flash Player to work with 64-bit Linux and Firefox.&lt;br /&gt;&lt;br /&gt;Because the Adobe Flash Player is &lt;span style="font-style:italic;"&gt;closed&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;proprietary&lt;/span&gt;, Linux distributions couldn't ship with it installed. Users would always have to jump through hoops such as configuring third-party package repositories in order to install it. &lt;br /&gt;&lt;br /&gt;Yes, as the author points out, flash is an open specification, so anyone technically &lt;span style="font-style:italic;"&gt;can&lt;/span&gt; implement it. But to date, there haven't been any open flash players that are worth a damn.  Open implementations such as Gnash are turds.  They are several versions of the flash specification out of date, their performance is abysmal, and getting them configured and working is black magic.  So let's leave flash's "openness" aside, because that's a red herring.&lt;br /&gt;&lt;br /&gt;What is material is that much of the Internet depends on your browser being able to play flash.  This is just as bad as the Internet of a few years ago requiring Internet Explorer, and being broken on every other browser.  An Internet dependent on Adobe Flash Player is bad for Linux users.  An Internet that has embraced HTML5, CSS, and Javascript is good for Linux users. Get off your Apple-hating high horse and acknowledge the fact that the two of you are on the same side.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-2072825454302393601?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/2072825454302393601/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=2072825454302393601' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/2072825454302393601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/2072825454302393601'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2010/05/remarks-on-apple-flash-and-i-hate-apple.html' title='Remarks on Apple, Flash and the &quot;I Hate Apple&quot; People'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-7077582668910801738</id><published>2009-08-31T17:16:00.002-04:00</published><updated>2009-08-31T17:24:42.034-04:00</updated><title type='text'>Ubuntu Netbook Remix in VMware</title><content type='html'>I needed to install Ubuntu Netbook Remix (UNR) in a VMware Virtual Machine so that I could try to reproduce a bug.  It was kind of an asspain. Problem is, UNR is made to be installed from a USB flash drive, and VMware can't boot from USB devices.  There isn't a DVD or CD ISO image for UNR 9.04 available.  It turns out that you can make a DVD image from the UNR .img.&lt;br /&gt;&lt;br /&gt;I found the following guide on the Ubuntu forums (see below for a link).  It should work from most linux distros:&lt;br /&gt;&lt;br /&gt;Make a directory to hold the contents of the UNR DVD image:&lt;pre&gt;&lt;br /&gt;$ mkdir unr&lt;/pre&gt;&lt;br /&gt;Make a mount point to mount the UNR .img file:&lt;pre&gt;&lt;br /&gt;$ mkdir realunr&lt;/pre&gt;&lt;br /&gt;Mount the UNR .img as a loop device:&lt;pre&gt;&lt;br /&gt;$ sudo mount -o loop -t vfat ubuntu-9.04-netbook-remix-i386.img realunr/&lt;/pre&gt;&lt;br /&gt;Copy all the contents from the UNR image to your unr/ directory.  Note that realunr/.diskimage is critical:&lt;pre&gt;$ rsync -a realunr/ unr/&lt;/pre&gt;&lt;br /&gt;Rename syslinux to isolinux:&lt;pre&gt;unr$ mv syslinux isolinux&lt;br /&gt;unr$ mv isolinux/syslinux.cfg isolinux/isolinux.cfg&lt;/pre&gt;&lt;br /&gt;Generate a DVD image from the contens of unr with the following incantation:&lt;pre&gt;mkisofs -o ubuntu-9.04-netbook-remix-i386.iso -r -J -l \&lt;br /&gt;-V "Ubuntu-Netbook-Remix 9.04 i386" -b isolinux/isolinux.bin \&lt;br /&gt;-c isolinux/boot.cat -no-emul-boot -boot-load-size 4 \&lt;br /&gt;-boot-info-table unr/&lt;/pre&gt;&lt;br /&gt;mkisofs will generate a DVD image that you can either boot a VM from or burn to a DVD.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ubuntuforums.org/showthread.php?t=1186567"&gt;Guide&lt;/a&gt; on ubuntuforums.org&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-7077582668910801738?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/7077582668910801738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=7077582668910801738' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7077582668910801738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7077582668910801738'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/08/ubuntu-netbook-remix-in-vmware.html' title='Ubuntu Netbook Remix in VMware'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-1408410370196510376</id><published>2009-08-07T18:16:00.004-04:00</published><updated>2009-08-07T18:45:34.040-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iPhone'/><title type='text'>Jailbroken iPhone, Cydia Apps, Upgrading iPhone to 3.0.1</title><content type='html'>I've been running my iPhone jailbroken for a couple of weeks.  At first I felt dirty about having callously cast aside many of the legitimate security mechanisms in the iPhone, such as sandboxing of 3rd party apps.  Utlimately, I have given into my baser instincts and am sticking with it.&lt;br /&gt;&lt;br /&gt;Today I upgraded my iPhone to 3.0.1.  There isn't an official jailbreak for 3.0.1 yet, but the 3.0 jailbreak works.  The problem in general with upgrading a jailbroken phone is that there's no real way to back up all of your unauthorized customizations.  You've basically had your way with the underlying Unix OS.  Not everything you install from Cydia is a self-contained app.  There are system modifications like installing OpenSSH and system utilities.  Anyway, what it comes down to is that you need to reinstall all of your Cydia packages after upgrading and re-jailbreaking.&lt;br /&gt;&lt;br /&gt;Here's how the process went for me:&lt;br /&gt;In iTunes:&lt;br /&gt;-do a backup&lt;br /&gt;-choose to restore, which will also update.  Don't choose upgrade.&lt;br /&gt;&lt;br /&gt;After this is done, leave itunes, and follow the normal jailbreak process&lt;br /&gt;-Run redsn0w&lt;br /&gt;-Point redsn0w at your 3.0 iPhone OS ipsw file.&lt;br /&gt;&lt;br /&gt;Once redsn0w is done, you're jailbroken again and running (mostly) 3.0.1.  You still need to reinstall your Cydia packages.  I found some of my customizations returned once I had reinstalled the Cydia packages, but not all.&lt;br /&gt;&lt;br /&gt;On the topic of Cydia packages, here's a list of packages that I installed and really like:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;BigBoss Recommended; This gets you a bunch of command line utilities that you'd expect to be on most unix systems.  It actually is a metapackage that brings a ton of other packages with it.&lt;/li&gt;&lt;li&gt;MobileTerminal; A terminal application (not an SSH client)&lt;/li&gt;&lt;li&gt;MusicControls; A paid app that lets you background and control many music applications like Slacker and Pandora&lt;/li&gt;&lt;li&gt;OpenSSH; client and server.  Be sure to reset passwords for root and mobile.  Also disable root logins.  Disable sshd from running automatically.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;SBSettings; let's you tweak many hidden settings, replacing BossPrefs.  Also required for disabling autostarting of the sshd service&lt;/li&gt;&lt;li&gt;Safari Download Manager; A paid app. Lets you download and save files, even ones that Safari doesn't know how to handle.  Great for downloading files and getting them off you phone.&lt;/li&gt;&lt;li&gt;iFile; A paid app that lets you browse the entire filesystem and open files.  Also has a built-in web server that will serve up files to your laptop.  Useful when you have no Internet, but need to download a file.&lt;/li&gt;&lt;li&gt;SysInfoPlus; Shows you lots of technical information about your iPhone.  Mostly just neat.&lt;/li&gt;&lt;li&gt;Status Notifier; shows various status indicators like new mail icon in the iPhones status bar at the top of the screen&lt;/li&gt;&lt;li&gt;BlackDarkness theme; This is a complete system theme that replaces lots of things, including many icons.  I think it's kind of neat.  Brings winterboard with it.&lt;/li&gt;&lt;/ul&gt;That's about it.  The BigBoss blog is recommending that you stand pat until there's a redsn0w update.  Supposedly it's going to make things a bit easier.  It's not clear in what way.  At the very least, they point out that for now, you'll still end up with a 3.0 kernel.  Hmmm.  :-/&lt;br /&gt;&lt;a href="http://thebigboss.org/2009/07/31/iphone-v301-released/"&gt;&lt;br /&gt;http://thebigboss.org/2009/07/31/iphone-v301-released/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-1408410370196510376?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/1408410370196510376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=1408410370196510376' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1408410370196510376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1408410370196510376'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/08/jailbroken-iphone-cydia-apps-upgrading.html' title='Jailbroken iPhone, Cydia Apps, Upgrading iPhone to 3.0.1'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-8408395296332122985</id><published>2009-06-13T10:04:00.001-04:00</published><updated>2009-06-13T11:12:35.636-04:00</updated><title type='text'>I'm on twitter</title><content type='html'>Feel free to &lt;a href="http://twitter.com/zcutlip"&gt;follow&lt;/a&gt; me.  The stuff I post there is awesome and will rock your world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-8408395296332122985?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/8408395296332122985/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=8408395296332122985' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/8408395296332122985'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/8408395296332122985'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/06/im-on-twitter.html' title='I&apos;m on twitter'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5041380812835564909</id><published>2009-06-11T20:47:00.002-04:00</published><updated>2009-06-11T21:05:33.853-04:00</updated><title type='text'>GEICO Music</title><content type='html'>I hate to admit it, but GEICO commercials have a pretty good track record for featuring good pop music.  Whether it's &lt;a href="http://www.geico.com/about/commercials/music/cavemen/"&gt;3 Doors Down&lt;/a&gt;, &lt;a href="http://royksopp.com/music/remind-me"&gt;Royksopp&lt;/a&gt;, or &lt;a href="http://www.youtube.com/watch?v=UBImCXj_CcM"&gt;The Sounds&lt;/a&gt;, the songs in GEICO's ads are usually pretty good.&lt;br /&gt;&lt;br /&gt;The latest that I like is "Somebody's Watching Me" by Mysto &amp;amp; Pizzi.  This song is featured in the ridiculous "Kash" commercials.  You can &lt;a href="http://www.geico.com/about/commercials/music/kash/"&gt;download&lt;/a&gt; it for free.  While you're there, check out the "making of" video.  It's surprisingly entertaining.&lt;br /&gt;&lt;br /&gt;I don't like the commercials, and I'm not about to switch insurance providers, but, in general, if you hear a song in a GEICO spot, you can probably add it to your library with no regrets.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5041380812835564909?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5041380812835564909/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5041380812835564909' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5041380812835564909'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5041380812835564909'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/06/geico-music.html' title='GEICO Music'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-2042513481953712766</id><published>2009-05-14T05:58:00.006-04:00</published><updated>2009-05-14T07:37:17.929-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Spotlight does Math</title><content type='html'>I just discovered that Leopard's Spotlight does math.  Try it.  Bring up spotlight with ⌘&lt;span style="font-family:courier new;"&gt;+space&lt;/span&gt;. Then start typing something like&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;7pi*8.3&lt;/span&gt; or&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sqrt(2)&lt;/span&gt;&lt;br /&gt;and the answer is the first search result.&lt;br /&gt;&lt;br /&gt;This isn't quite a powerful as the Google calculator.  It doesn't appear to do base conversion, and it doesn't let you copy the result for pasting into an application, but it seems handy nonetheless.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-2042513481953712766?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/2042513481953712766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=2042513481953712766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/2042513481953712766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/2042513481953712766'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/05/spotlight-does-math.html' title='Spotlight does Math'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-1570983612699088990</id><published>2009-05-06T19:34:00.003-04:00</published><updated>2009-05-14T07:37:10.085-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>Mac OS X handy bash aliases</title><content type='html'>Here are a few handy aliases that I keep in my .bashrc in OS X:&lt;br /&gt;&lt;pre&gt;alias cppwd='eval "echo `pwd` | tr -d \\\\n | pbcopy"'&lt;/pre&gt; This copies my current working directory to the OS X pasteboard so I can Cmd+V it into another terminal.  Often I want several terminals open in the same directory at once.&lt;br /&gt;&lt;pre&gt;alias burn='drutil burn -noverify'&lt;/pre&gt; This one lets me type&lt;br /&gt;&lt;pre&gt;burn mydisc.iso&lt;/pre&gt; to burn an ISO disc image to CD or DVD without having to open Disk Utility.&lt;br /&gt;And a variation:&lt;br /&gt;&lt;pre&gt;alias vburn='drutil burn'&lt;/pre&gt; This does the same as the other but also does the disc verification step.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-1570983612699088990?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/1570983612699088990/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=1570983612699088990' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1570983612699088990'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1570983612699088990'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/05/mac-os-x-handy-aliases.html' title='Mac OS X handy bash aliases'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-3490196595978289361</id><published>2009-04-15T08:57:00.003-04:00</published><updated>2009-05-14T07:34:35.591-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='timehole'/><title type='text'>A Gun for the Time Hole</title><content type='html'>An ordinary &lt;a href="http://en.wikipedia.org/wiki/Ak-47"&gt;AK-47&lt;/a&gt; Kalashnikov automatic rifle would not be allowed through the &lt;a href="http://shadow-file.blogspot.com/2009/03/rules-of-time-hole.html"&gt;time hole&lt;/a&gt;.  One made of &lt;a href="http://www.thisisfreakingridiculous.com/tifr/2009/4/13/ba-k-47.html"&gt;bacon&lt;/a&gt;, however, is an ideal candidate for the time-traveling freedom fighter.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.thisisfreakingridiculous.com/storage/post-images/gun6.jpg?__SQUARESPACE_CACHEVERSION=1239677315557"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 500px; height: 375px;" src="http://www.thisisfreakingridiculous.com/storage/post-images/gun6.jpg?__SQUARESPACE_CACHEVERSION=1239677315557" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-3490196595978289361?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/3490196595978289361/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=3490196595978289361' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3490196595978289361'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3490196595978289361'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/04/gun-for-time-hole.html' title='A Gun for the Time Hole'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-900977490068329346</id><published>2009-03-23T07:19:00.004-04:00</published><updated>2009-03-23T07:21:10.670-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FiOS'/><title type='text'>FiOS at Work</title><content type='html'>&lt;img src="http://www.speedtest.net/result/435194800.png" /&gt;&lt;br /&gt;&lt;br /&gt;Finally.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-900977490068329346?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/900977490068329346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=900977490068329346' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/900977490068329346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/900977490068329346'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/03/fios-at-work.html' title='FiOS at Work'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5793271191566636008</id><published>2009-03-15T12:18:00.003-04:00</published><updated>2009-05-14T07:35:13.097-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Handling HTTP Redirection in Ruby</title><content type='html'>I have a Ruby project where I'm dumping a bunch of bookmarks from delicious.com, then fetching each bookmarked page for analysis.&lt;br /&gt;&lt;br /&gt;One of the problems I encountered early on is that the some of the web pages bookmarked would redirect to some other location.  Simply checking for HTTP response code 200 was insufficient.  I needed to check for redirection as well.&lt;br /&gt;&lt;br /&gt;A quick Google search for "ruby follow http redirect" yields lots of &lt;a href="http://www.google.com/search?q=ruby+follow+http+redirect&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:en-US:official&amp;amp;client=firefox-a"&gt;results&lt;/a&gt;.  Unfortunately, they're all very similar, and not quite right.  In general, the examples you come across (even the one in the official Ruby documentation) don't handle the case when the redirected location is path relative to the original location.  So you end up doing a get on a URL that looks like "../../redirected/location/index.html," which clearly won't work.&lt;br /&gt;&lt;br /&gt;It turns out that detecting relative redirection is fairly straightforward:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; until( found || attempts&gt;=@@MAX_ATTEMPTS)&lt;br /&gt;     attempts+=1&lt;br /&gt;     http=Net::HTTP.new(url.host,url.port)&lt;br /&gt;     http.open_timeout = 10&lt;br /&gt;     http.read_timeout = 10&lt;br /&gt;     path=url.path&lt;br /&gt;     path="/" if path==""&lt;br /&gt;&lt;br /&gt;     req=Net::HTTP::Get.new(path,{'User-Agent'=&gt;@@AGENT})&lt;br /&gt;     if url.instance_of? URI::HTTPS&lt;br /&gt;       http.use_ssl=true&lt;br /&gt;       http.verify_mode = OpenSSL::SSL::VERIFY_NONE&lt;br /&gt;     end&lt;br /&gt;     resp=http.request(req)&lt;br /&gt;     if resp.code=="200"&lt;br /&gt;       break&lt;br /&gt;     end&lt;br /&gt;     if (resp.header['location']!=nil)&lt;br /&gt;       newurl=URI.parse(resp.header['location'])&lt;br /&gt;       if(newurl.relative?)&lt;br /&gt;           puts "url was relative"&lt;br /&gt;           newurl=url+resp.header['location']&lt;br /&gt;       end&lt;br /&gt;       url=newurl&lt;br /&gt;&lt;br /&gt;     else&lt;br /&gt;       found=true #resp was 404, etc&lt;br /&gt;     end #end if location&lt;br /&gt;   end #until&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The trick here is to ask the redirected url object if it is relative.  If it is, then add the redirected path onto the old url object.  the URI class overrides the '+' operator (what is this, C++?) so that you can concatenate the new path onto the old URL, by doing:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;newurl=url+resp.header['location']&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5793271191566636008?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5793271191566636008/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5793271191566636008' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5793271191566636008'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5793271191566636008'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/03/handling-http-redirection-in-ruby.html' title='Handling HTTP Redirection in Ruby'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-2395144200019468755</id><published>2009-03-12T09:30:00.006-04:00</published><updated>2009-05-14T07:35:30.365-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Mounting LVM Disks in Ubuntu</title><content type='html'>I always thought LVM (Linux's Logical Volume Manager) was kind of neat for the flexibility it gives you in adding and removing disks and resizing volumes such.  However, in practice, I find it's usually more trouble than it's worth.  It adds a layer of complexity between me and my data.&lt;br /&gt;&lt;br /&gt;Often I need to mount a disk configured with LVM on another Linux machine or in an Ubuntu live CD environment.  Out of the box the logical volumes aren't recognized, so I can't mount them.&lt;br /&gt;&lt;br /&gt;It's fairly easy to add LVM support and mount the volumes though.&lt;br /&gt;&lt;br /&gt;You install the lvm2 package, load the device mapper kernel module, and then activate any lvm volume groups on your disk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ sudo apt-get install lvm2&lt;br /&gt;$ sudo modprobe dm-mod&lt;br /&gt;$ sudo vgchange -a y&lt;/span&gt;&lt;br /&gt;(assuming your disk with logical volumes is already connected)&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ sudo mount /dev/mapper/&amp;lt;logical volume name&amp;gt; /mnt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And that's all there is to it.&lt;br /&gt;&lt;br /&gt;If you want to deactivate the volume groups (recommended before unplugging a USB disk with logical volumes):&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;$ sudo vgchange -a n&lt;/span&gt;&lt;br /&gt;Warning: the above command will deactivate &lt;span style="font-style: italic;"&gt;all&lt;/span&gt; volume groups, so check the vgchange manpage first, if that's not what you want.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-2395144200019468755?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/2395144200019468755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=2395144200019468755' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/2395144200019468755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/2395144200019468755'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/03/mounting-lvm-disks-in-ubuntu.html' title='Mounting LVM Disks in Ubuntu'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-1941536381657347683</id><published>2009-03-09T20:25:00.011-04:00</published><updated>2012-01-28T00:35:01.597-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='timehole'/><title type='text'>The Rules of the Time Hole</title><content type='html'>There was a great video on College Humor addressing why terminators travel back in time naked.&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="338" src="http://www.collegehumor.com/e/3915529" webkitallowfullscreen="" width="600"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;div style="padding: 5px 0; text-align: center; width: 600px;"&gt;&lt;a href="http://www.collegehumor.com/videos"&gt;See more at CollegeHumor&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;That said, I think it's worth discussing the rules of time travel or "the time hole" as my colleague Ross and I put it.  So if you've followed the Terminator movies, and, more recently, Terminator: The Sarah Connor Chronicles, the rules of the time hole are fairly easy to infer.&lt;br /&gt;&lt;br /&gt;Things can go through the time hole if:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;They are made of meat&lt;/li&gt;&lt;li&gt;They are wrappped in meat&lt;/li&gt;&lt;li&gt;They look very much like they are made of meat&lt;/li&gt;&lt;li&gt;If several things meeting the above rules go through all at once, something else may sneak through behind them.&lt;/li&gt;&lt;/ol&gt;In the original Terminator movie, we saw Kyle Reese, John Connor's soon-to-be father, come through the time hole.  As he is 100% human, Kyle clearly qualifies for time travel under rule #1--he is made of meat.  Also in the same film, the Terminator, a Cyberdyne Systems Model 101, comes through the time hole, qualifying under rule #2.  The 101 consists of a metal skeleton that is &lt;span style="font-style: italic;"&gt;wrapped in meat&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;In Terminator 2, we see the T-1000, which is constructed of a  "mimetic poly-alloy," i.e., liquid metal, travel through time.  Clearly, the T-1000 qualifies under rule #3 as it looks, very convincingly, like it is made of meat.  Similarly, in Terminator 3, we see the T-X come back in time.  The T-X is much like the T-1000, except hot.&lt;br /&gt;&lt;br /&gt;Later, in the The Sarah Connor Chronicles, we see Cameron (a terminator wrapped in meat), John, and Sarah (both made of meat) travel back in time.  However, just before the time hole closes, Cromartie's severed head (devoid of its meat wrapping) flies through after them.&lt;br /&gt;&lt;br /&gt;I checked all terminator-related facts presented above on &lt;a href="http://en.wikipedia.org/wiki/Terminator_%28character_concept%29"&gt;wikipedia.org&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-1941536381657347683?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/1941536381657347683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=1941536381657347683' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1941536381657347683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1941536381657347683'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/03/rules-of-time-hole.html' title='The Rules of the Time Hole'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-6820913252048856486</id><published>2009-01-10T17:36:00.002-05:00</published><updated>2009-05-14T07:37:27.732-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='apple'/><title type='text'>OS X: How to detect whether you're on battery from the shell</title><content type='html'>Sometimes you need to determine programatically whether a computer is on battery or on AC.  For example, I have a backup script that takes hourly snapshots of my home directory on my MacBook Pro (which I hopefully will post about at some point).  However, I don't want the script to run if I'm on battery.  Ideally, &lt;span style="font-family:courier new;"&gt;launchd&lt;/span&gt;, which kicks off the script, could give me this option, but I don't think it can.  I'll have to let the script make the decision when it gets executed.&lt;br /&gt;&lt;br /&gt;If I were writing the script for Linux, I'd have it look through &lt;span style="font-family:courier new;"&gt;/proc/acpi/&lt;/span&gt; to check the state of the battery.  There's no &lt;span style="font-family:courier new;"&gt;/proc&lt;/span&gt; in OS X.  There is, however, a power management command, &lt;span style="font-family:courier new;"&gt;pmset&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;If I run pmset -g while on AC, I get:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Currently drawing from 'AC Power'&lt;br /&gt;-InternalBattery-0     100%; AC attached; not charging&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If I run it while on battery, I get:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Currently drawing from 'Battery Power'&lt;br /&gt;-InternalBattery-0     100%; discharging; (no estimate)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I simply have my script grep the output from pmset for "discharging":&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;checkBattery()&lt;br /&gt;{&lt;br /&gt;     local ret=0;&lt;br /&gt;     if $PMSET -g batt | $GREP -q discharging;&lt;br /&gt;     then&lt;br /&gt;             ret=1;&lt;br /&gt;     fi&lt;br /&gt;     return $ret;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;See the pmset(1) manpage for more info.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-6820913252048856486?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/6820913252048856486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=6820913252048856486' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/6820913252048856486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/6820913252048856486'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/01/os-x-how-to-detect-whether-youre-on.html' title='OS X: How to detect whether you&apos;re on battery from the shell'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-3048583374434359035</id><published>2009-01-09T19:07:00.003-05:00</published><updated>2009-05-14T07:36:59.893-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Converting a .dmg to a .iso</title><content type='html'>I have an operating system install image that I need to install in VMware Fusion.   The problem is the install image is a MacOS disk image file, or .dmg.  I need a DVD image, or a .iso, in order to boot the VM and do the install.&lt;br /&gt;&lt;br /&gt;It turns out that the Mac OS X command hdiutil to convert the .dmg to a .iso:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;hdiutil convert &lt;original&gt;.dmg -format UDTO -o &lt;new&gt;.iso&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;See the hdiutil(1) manpage for more info.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-3048583374434359035?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/3048583374434359035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=3048583374434359035' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3048583374434359035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3048583374434359035'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/01/converting-dmg-to-iso.html' title='Converting a .dmg to a .iso'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-806471265228549156</id><published>2009-01-08T09:31:00.009-05:00</published><updated>2009-12-21T06:08:19.339-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>How to sudoedit non-interactively</title><content type='html'>Okay, this one's a bit esoteric, but I think it's pretty cool.  How do you use 'sudoedit' non-interactively such as from a script?  Just a brief background about sudo: sudo is an authentication mechanism in Unix &amp;amp; Linux that allows unprivileged users to run specific commands (as defined by the system administrator) with root privileges without having the root password.  This has several advantages over logging in as root:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Users can have specific, limited set of root privileges without having the entire set of root privileges.&lt;/li&gt;&lt;li&gt;Users use their &lt;span style="font-style: italic;"&gt;own&lt;/span&gt; password, so the root password doesn't have to be shared.  If a user's sudo privileges are revoked, the root password doesn't have to be reset.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Each use of sudo is audited per user, so that each time sudo privileges are invoked, there is an event in the system logs that identifies the specific user and the command they ran.&lt;/li&gt;&lt;/ul&gt;Sudoedit is a command that is related to sudo.  It lets users edit files that normally only root can edit, such as system configuration files.  However instead of using "sudo" followed by the editing command, the user runs "sudoedit filename" and sudo invokes the user's default editor, letting them edit the file.&lt;br /&gt;&lt;br /&gt;So, what if you want to make changes to a system file via a script, and the only access you have to the file is via sudoedit?  It isn't useful to have the script call sudoedit and then bring up vi for you to manually make the changes.&lt;br /&gt;&lt;br /&gt;Well, the way sudoedit works, is that sudo makes a temporary copy of the file you want to edit, then calls your default editor, giving it the name of the temp file as the first argument.  So, say your default editor is "fooedit".  You run "sudoedit /etc/systemfile" and sudo makes a copy of /etc/systemfile to /tmp then runs "fooedit /tmp/tempfile".  Your changes are saved to the temp file.  When your editor exits, sudo copies the temp file over the original, and then removes the temp file.&lt;br /&gt;&lt;br /&gt;From your main script, stage the pre-edited version of the system file, then set your default editor to a custom script that will copy that staged file over the temp file.  When it exits, sudo will copy the temp file into place as normal.&lt;br /&gt;&lt;br /&gt;Your script would go like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;&lt;br /&gt;export EDITOR="/bin/sh ./editor.sh";&lt;br /&gt;PRE_STAGE=/tmp/stage.tmp;&lt;br /&gt;&lt;br /&gt;echo "my new config"&gt; $PRE_STAGE;&lt;br /&gt;&lt;br /&gt;sudoedit /etc/config;&lt;br /&gt;&lt;br /&gt;/bin/rm $PRE_STAGE;&lt;br /&gt;&lt;br /&gt;exit;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Your custom script would look like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;CAT=/bin/cat&lt;br /&gt;PRE_STAGE="/tmp/stage.tmp"&lt;br /&gt;&lt;br /&gt;$CAT $PRE_STAGE &gt; "$1";&lt;br /&gt;exit;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This script just cats your pre-staged file over whatever sudo passed in as the first argument ($1).&lt;br /&gt;&lt;br /&gt;The only interaction you'll have to do is type your password for sudo, if you haven't already done so in the last few minutes (sudo temporarily remembers your authentication).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-806471265228549156?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/806471265228549156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=806471265228549156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/806471265228549156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/806471265228549156'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2009/01/how-to-sudoedit-non-interactively.html' title='How to sudoedit non-interactively'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-1952814488933143908</id><published>2008-12-21T10:51:00.005-05:00</published><updated>2008-12-21T11:21:30.224-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='mythtv'/><title type='text'>NVIDIA's Game-Changing Video Accelaration in Linux</title><content type='html'>Recently NVIDIA &lt;a href="http://www.phoronix.com/scan.php?page=article&amp;amp;item=nvidia_vdpau_gpu&amp;amp;num=1"&gt;introduced&lt;/a&gt; their Video Decode and Presentation API for Unix, or VDPAU, along with support in their beta 180.xx drivers.  This API allows application developers to offload decoding and rendering to the system's NVIDIA video card.  Graphics cards have long had some level of hardware assist for video decoding, but this lets applications offload almost all the work to the GPU.  I believe NVIDIA calls this capability "Pure Video" in Windows.&lt;br /&gt;&lt;br /&gt;Since I've been &lt;a href="http://shadow-file.blogspot.com/2008/12/mythtv-hd-pvr-trunk.html"&gt;experimenting&lt;/a&gt; with HD recording in MythTV, I decided to give the new drivers a try.  You have to download the latest beta Linux drivers from NVIDIA.  See the &lt;a href="http://www.nvnews.net/vbulletin/forumdisplay.php?f=14"&gt;nvnews forum&lt;/a&gt; to find out what the latest release is.  NVIDIA doesn't advertise beta releases.  You also need an NVIDIA GeForce 8xxx or 9xxx GPU.&lt;br /&gt;&lt;br /&gt;In order to take advantage of VDPAU in MythTV, you have to build from trunk.  See the MythTV VDPAU wiki &lt;a href="http://www.mythtv.org/wiki/index.php/VDPAU"&gt;article&lt;/a&gt; for more information.&lt;br /&gt;&lt;br /&gt;I gave this a try and the results are amazing.  The test system is a circa 2004 Athlon 64.  Without VDPAU, the CPU was maxed out between video decoding and X's rendering.   With VDPAU, cpu utilization was between 5 and 8 %.  This was watching Live TV, which meant recording, encoding, decoding and rendering.   This is a complete game-changer for MythTV.  One of the biggest problems with MythTV, and other homebrew PVRs, is that the frontend needs to be fairly powerful.  Generally this means around $500 for a capable system.  It's hard to justify spending this much money in each room you want to watch TV (though I've managed to rationalize it anyway ;-).  What this means is it is now theoretically possible to use a very cheap system for a frontend as long as it has an NVIDIA GPU in it.  There are a number of low-profile graphics cards on Newegg for around $40-$50.  Also, NVIDIA's &lt;a href="http://gizmodo.com/5111999/nvidia-ion-supercharges-netbooks-with-5x-faster-graphics-and-full-hd-video"&gt;Ion&lt;/a&gt; chipset looks especially interesting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-1952814488933143908?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/1952814488933143908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=1952814488933143908' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1952814488933143908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1952814488933143908'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/12/nvidias-game-changing-video.html' title='NVIDIA&apos;s Game-Changing Video Accelaration in Linux'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-7677378877409230608</id><published>2008-12-21T10:22:00.005-05:00</published><updated>2008-12-21T11:22:07.096-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='mythtv'/><title type='text'>MythTV, HD-PVR, Trunk</title><content type='html'>Until Hauppauge released the HD-PVR this past May, there was no way to record in high-definition from your cable or satellite box.  Your HD recording options were limited to over-the-air, unencrypted QAM, or, in rare instances, unencrypted firewire from the cable box.  In any case there was no way to record the good stuff in HD.  I'll spare the details about the HD-PVR itself, and instead include some links at the end.&lt;br /&gt;&lt;br /&gt;Of course, Linux support for the HD-PVR wasn't available straight away.  However, this is a big breakthrough for homebrew PVRs so the MythTV/Linux community has been hard at work.  It there is a Linux driver for the HD-PVR, but you have to check it out and build it yourself (See links at the end).  Also, early work has been done on MythTV to support the HD-PVR, but in order to get that support, you have to run MythTV from trunk, rather than using your distribution's packaged version.  This means checking out source and building it yourself.  The source code changes daily, and at times things get worse before they get better.  Whatever you check out on any given day should be in decent shape, but it may not be.  You are forging MythTV from the molten center of the Earth, and it's still hot and a little bit on fire.&lt;br /&gt;&lt;br /&gt;What is now in trunk will eventually make it into your distribution, but there's generally a 6-12 month lag, depending on your distribution's release cycle.  Well, I'm ready to give the HD-PVR a try now, so I decided to give trunk a go.  I set up a spare machine on my work bench to be a frontend and backend.  After getting the HD-PVR drivers compiled and working, I checked out MythTV from subversion and built it.  There are good documents detailing how to do this.  It's actually not that hard.  The build system for MythTV is very nice.  I recommend starting with a MythTV based distribution like Mythbuntu, and removing all the mythtv packages.  This will save you a lot of grunt work like setting up MySQL, the mythtv user, init script, etc.&lt;br /&gt;&lt;br /&gt;Anyway, I've got the HD-PVR working with MythTV.  I haven't used it for any actual TV watching or recording yet.  As soon as I can get a frontend set up, I'll be able to actually try using it day-to-day.&lt;br /&gt;&lt;br /&gt;Relevant links:&lt;br /&gt;&lt;a href="http://www.geektonic.com/2008/06/hauppauge-hd-pvr-unboxing-first-look.html"&gt;http://www.geektonic.com/2008/06/hauppauge-hd-pvr-unboxing-first-look.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mythtvnews.com/2008/05/30/hauppauge-hd-pvr-support-coming-for-mythtv-devices-are-shipping-now/"&gt;http://mythtvnews.com/2008/05/30/hauppauge-hd-pvr-support-coming-for-mythtv-devices-are-shipping-now/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://mythtvnews.com/2008/06/14/hauppauge-hd-pvr-linux-driver-released-alpha-quality/"&gt;http://mythtvnews.com/2008/06/14/hauppauge-hd-pvr-linux-driver-released-alpha-quality/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.mythtv.org/wiki/index.php/Ubuntu_Installation_Guides"&gt;http://www.mythtv.org/wiki/index.php/Ubuntu_Installation_Guides&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.mythtv.org/wiki/index.php/Hauppauge_HD-PVR"&gt;http://www.mythtv.org/wiki/index.php/Hauppauge_HD-PVR&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-7677378877409230608?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/7677378877409230608/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=7677378877409230608' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7677378877409230608'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7677378877409230608'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/12/mythtv-hd-pvr-trunk.html' title='MythTV, HD-PVR, Trunk'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-3734673020575654811</id><published>2008-12-21T09:17:00.007-05:00</published><updated>2008-12-21T10:21:09.915-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Ditching apt-cacher-ng for Squid</title><content type='html'>&lt;a href="http://shadow-file.blogspot.com/2008/09/apt-cacher-ng.html"&gt;apt-cacher-ng &lt;/a&gt;hasn't exactly worked out as well as I had hoped.  I kept having a problem where the Releases file from the apt repository would be reported as corrupted.  I could go into the cache directory and manually remove that file, forcing it to be downloaded again, but that would only help with the system I was updating at the moment.  The next system that I tried to update would have the same problem.&lt;br /&gt;&lt;br /&gt;I've read a number of articles about just using Squid as an apt cache.  I avoided this at first because Squid isn't really made for that.  For example squid has no way of knowing when a specific version of a package has been made obsolete by a newer version.  I assume apt-cacher-ng and apt-proxy know how to do this (maybe not).  Also Squid isn't intended to cache arbitrarily sized objects for indefinite periods of time.  I decided to give it a try though, since a number of people seem to be having success with this.&lt;br /&gt;&lt;br /&gt;I had to tweak Squid's default configuration a bit to make it suitable for apt-caching.&lt;br /&gt;The Squid configuration file is well documented, but below are the directives of interest:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;refresh_pattern deb$            1577846 100%    1577846&lt;br /&gt;refresh_pattern Packages.gz$    1440    100%    1440&lt;br /&gt;cache_dir ufs /var/spool/squid 15000 2 8&lt;br /&gt;maximum_object_size 409600 KB&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The first line says to cache anything ending ('$' is the end-of-line anchor) in "deb" for 3 years.  There are some packages that rarely get updated if ever, so I want to make they stay in the cache the entire time I'm using a given distribution release.  I figure I'll probably be on a particular distribution release for no longer than three years.&lt;br /&gt;&lt;br /&gt;The second line says to cache anything ending in "Packages.gz" for one day.&lt;br /&gt;&lt;br /&gt;The "cache_dir" line says to put Squid's cache in /var/spool/squid (I believe this is the default).  It also says to let it grow no larger than 15,000 megabytes.  My system partition gets very little use, so 15Gb is no problem for me.  The second two numbers tell Squid how to structure the cache.  "2" says to create two level 1 directories and "8" says to create 8 level 2 directories.  The default is 16 and 256.  I read an article where the author was having a problem with the hard drive never spinning down because Squid was rescanning the cache every few seconds.  The author said reducing the number of L1 and L2 directories helped.  If anyone can find this article, please post a link in the comments.&lt;br /&gt;&lt;br /&gt;The "maximum_object_size"  tells squid to cache objects up to 400Mb.  There shouldn't be any debs even close to that large.  Squid's default is much smaller than this.&lt;br /&gt;&lt;br /&gt;In order to get apt to use the proxy, I created a file called "proxy" in /etc/apt/apt.conf.d/.  You can call the file whatever you want.   The file contains the line:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Acquire::http::Proxy "http://hoth:3128";&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;"hoth" is the hostname of the Squid server.  Make sure there are no "Acquire" directives in any other apt configuration file:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;/etc/apt/ # grep -rn Acquire *&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;I discovered that on some systems there was an "Acquire" directive explicitly telling apt &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; to use a proxy.&lt;br /&gt;&lt;br /&gt;So far, Squid has been working pretty well. There was one instance where apt failed to completely download a package, but after running apt-get dist-upgrade again, the package successfully downloaded.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-3734673020575654811?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/3734673020575654811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=3734673020575654811' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3734673020575654811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3734673020575654811'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/12/ditching-apt-cacher-ng-for-squid.html' title='Ditching apt-cacher-ng for Squid'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-8386089343916294232</id><published>2008-12-21T09:13:00.003-05:00</published><updated>2008-12-21T09:16:38.451-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='class'/><title type='text'>End of Semester</title><content type='html'>Well the fall semester finally ended.   Between TA work, the IDS class, the &lt;a title="Java EE class" href="http://shadow-file.blogspot.com/2008/09/enterprise-java-class.html" id="u-0s"&gt;Java EE class&lt;/a&gt; and my actual job, this semester was a &lt;i&gt;lot&lt;/i&gt; of work.  Java EE wasn't 15 hours a week as anticipated.  More like 20-30 hour each week, with a couple weeks (right before projects were due) around 55-60 hours.  I did end up with As in both classes, though.  Anyway, now I'm getting caught up on all that sitting around doing nothing that I've neglected for the last four months.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-8386089343916294232?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/8386089343916294232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=8386089343916294232' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/8386089343916294232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/8386089343916294232'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/12/end-of-semester.html' title='End of Semester'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-3396011575999030753</id><published>2008-10-07T17:52:00.004-04:00</published><updated>2009-05-14T07:36:26.044-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FiOS'/><title type='text'>FiOS</title><content type='html'>We just got our FiOS internet hooked up. I opted for the 20Mbs up, 5Mbs down option. Here's a bandwith test from speedtest.net:&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.speedtest.net/result/334832889.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://www.speedtest.net/result/334832889.png" alt="" border="0" /&gt;&lt;/a&gt;Other than being &lt;span style="font-style: italic;"&gt;really&lt;/span&gt; annoyed at how difficult (i.e. almost impossible) Verizon makes it to use your own router instead of theirs, it's pretty awesome.  I'm in the process of &lt;font face="courier"&gt;wget&lt;/font&gt;-ting the internet as we speak.  Starting with .com.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-3396011575999030753?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/3396011575999030753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=3396011575999030753' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3396011575999030753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3396011575999030753'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/10/fios.html' title='FiOS'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-3334423325609345333</id><published>2008-10-01T08:20:00.003-04:00</published><updated>2008-10-01T08:24:07.957-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='os x'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Awesome Log Message</title><content type='html'>I saw the greatest log message in my MacBook's system log this morning.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;SyncServer[8551]: SyncServer: Truth vacuumed. Next vacuum date 2008-10-15 08:13:17 -0400&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I'm sure it's something normal, and, given appropriate context, would make perfect sense.  But I am just amused that the SyncServer is vacuuming up all the truth.  No wonder I have a hard time finding useful log messages when I'm trying to troubleshoot something.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-3334423325609345333?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/3334423325609345333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=3334423325609345333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3334423325609345333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/3334423325609345333'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/10/awesome-log-message.html' title='Awesome Log Message'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-4426328172911268253</id><published>2008-09-13T13:00:00.003-04:00</published><updated>2008-09-13T13:33:38.467-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='iTunes'/><category scheme='http://www.blogger.com/atom/ns#' term='squeezebox'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>iTunes and Squeezebox Integration</title><content type='html'>I've discovered something very cool with &lt;a href="http://www.slimdevices.com/"&gt;Squeezebox&lt;/a&gt;.  iTunes integration.  Okay, I've known all along that Squeezebox (more accurately, Squeezecenter, the backend software) can use your iTunes library, but I've never tried it.  My network configuration is orders of magnitude more complex that most people's is.  I assumed you needed to be running Squeezecenter on the same system (i.e., your desktop) as where you were running iTunes.  Moreover, I assumed it would choke if its view of where the music lives was different that that of iTunes.&lt;br /&gt;&lt;br /&gt;On my network, we use NFS homes and shares mounted at /Network/Servers/hoth/&lt;&gt; on our MacBooks.  On the file server, the music share is found under /share/mp3s/music (sans the /Network/Servers/hoth).  And the iTunes library (I'm using Steph's) on the server is under /home/steph/Music/iTunes (again sans the /Network...).  I thought these differences alone constituted a recipe for fail.&lt;br /&gt;&lt;br /&gt;Well I gave it a try this morning, and a few minor gotchas notwithstanding, it works great for me.  You tell Squeezecenter where the iTunes xml file is located, as well as "where the music really lives", and it rescans your library and imports playlists (including snapshots of smart playlists).  Evidently, it doesn't take the iTunes library's view of the where the music lives as gospel.&lt;br /&gt;&lt;br /&gt;The gotchas were easy to deal with.  One, which I anticipated was read permission on Steph's iTunes library, which is buried deep in her home directory, whose perms are 700.  I fixed this with a little posix acl work (I &amp;lt;3 teh acls).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;/home # setfacl  -m u:squeezecenter:r-X steph&lt;br /&gt;/home # setfacl -R -m  u:squeezecenter:r-X steph/Music&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And make sure new files and dirs created get the right acl:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;/home # sudo setfacl -R -d -m  u:squeezecenter:r-X steph/Music&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;'mkay, with that solved, I told Squeezecenter where to find the iTunes sauce.  It was hard to tell if it was actually using the iTunes library or not, since it's the same set of music either way.  However, no new playlists showed up, so I guessed it didn't take.  Blanking out the path to the music and playlists that Squeezecenter uses in its "normal," non-iTunesey mode of operation, then reconfiguring the iTunes stuff, did the trick.  Now I'm listening to Steph's awesome playlists on the downstairs Squeezebox.&lt;br /&gt;&lt;br /&gt;Further, this solves the problem of how to get playlists into Squeezecenter.  Don't get me wrong--it's totally balls that iTunes won't export (or even import!) m3u playlists.  But at least we have a good (better?) workaround.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-4426328172911268253?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/4426328172911268253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=4426328172911268253' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/4426328172911268253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/4426328172911268253'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/09/itunes-and-squeezebox-integration.html' title='iTunes and Squeezebox Integration'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-1361033752336508328</id><published>2008-09-09T08:34:00.005-04:00</published><updated>2008-10-27T07:51:39.768-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>apt-cacher-ng</title><content type='html'>I have several machines on my network running &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Ubuntu&lt;/span&gt; Linux which need to be updated regularly to keep up with security updates and the like.  Several months ago I decided to try using a caching proxy to get updates from the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Ubuntu&lt;/span&gt; package repositories in order to reduce load on the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Ubuntu&lt;/span&gt; servers as well as to speed up the updating process on my systems.  After spending some time using apt-proxy, and being generally dissatisfied with its reliability, I decided to give &lt;a href="http://www.unix-ag.uni-kl.de/%7Ebloch/acng"&gt;apt-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;cacher&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;ng&lt;/span&gt;&lt;/a&gt; a try.&lt;br /&gt;&lt;br /&gt;Unfortunately apt-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;cacher&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;ng's&lt;/span&gt; documentation is a bit inaccessible.   Aside from not being available on the project's website (it's in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;PDF&lt;/span&gt; form in the documentation directory &lt;span style="font-style: italic;"&gt;after&lt;/span&gt; you install it), the documentation, although complete, is kind of impenetrable.  There also really isn't anything that I could find along the lines of HOW-TO&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;s&lt;/span&gt; or FAQs on the 'tubes.  I eventually got it worked out, and, at least for the common case, it turned out to be more straight-forward than the documentation leads you to believe.  Here's how I set mine up.&lt;br /&gt;&lt;br /&gt;I put entries in my &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;acng&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;conf&lt;/span&gt; like the following:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Remap-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;ubuntu&lt;/span&gt;: http://us.archive.ubuntu.com/ubuntu&lt;br /&gt;Remap-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;medibuntu&lt;/span&gt;: http://packages.medibuntu.org/&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The way this works is you specify names for each Remap-[whatever] where [whatever] is whatever you want to call it--they just have to be unique.  Then the part after the ':' is the literal &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_13"&gt;URL&lt;/span&gt; of the repository you're caching including the directory path on that server, if there is one.&lt;br /&gt;&lt;br /&gt;The documentation describes a third part that follows a ";".  If your second part is the actual URL of the repository, you don't need the third part, as you see above.&lt;br /&gt;&lt;br /&gt;In my sources.list, I put&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;deb http://&lt;span style="font-style: italic;"&gt;my-server-name&lt;/span&gt;:3142/packages.medibuntu.org hardy free non-free&lt;br /&gt;deb http://&lt;span style="font-style: italic;"&gt;my-server-name&lt;/span&gt;:3142/us.archive.ubuntu.com/ubuntu hardy main restricted universe &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;multiverse&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Here, the &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_15"&gt;URL&lt;/span&gt; to the apt repositories is your local server name (port is 3142 unless you change it in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;acng&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;conf&lt;/span&gt;) followed by a &lt;span style="font-style: italic;"&gt;directory&lt;/span&gt; that is the exact same as whatever the fully qualified domain name of the real apt repository was, followed by the actual directory path that you  appended to the actual apt repository in your &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;acng&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;conf&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;There are lots of other options described in the apt-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;cacher&lt;/span&gt;-&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;ng&lt;/span&gt; documentation, but I believe this is the common case, and it's working fine so far.&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;The directory structure that gets created under /var/cache looks like:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;apt-cacher-ng&lt;br /&gt;|-- canonical-partner&lt;br /&gt;|   `-- dists&lt;br /&gt;|       `-- hardy&lt;br /&gt;|-- ubuntu&lt;br /&gt;|   |-- dists&lt;br /&gt;|   |   |-- hardy&lt;br /&gt;|   |   |-- hardy-backports&lt;br /&gt;|   |   `-- hardy-updates&lt;br /&gt;|   `-- pool&lt;br /&gt;|       |-- main&lt;br /&gt;|       |-- restricted&lt;br /&gt;|       `-- universe&lt;br /&gt;`-- ubuntu-security&lt;br /&gt;    |-- dists&lt;br /&gt;    |   `-- hardy-security&lt;br /&gt;    `-- pool&lt;br /&gt;        |-- main&lt;br /&gt;        |-- multiverse&lt;br /&gt;        `-- universe&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-1361033752336508328?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/1361033752336508328/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=1361033752336508328' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1361033752336508328'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1361033752336508328'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/09/apt-cacher-ng.html' title='apt-cacher-ng'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5508069880665417003</id><published>2008-09-07T17:51:00.004-04:00</published><updated>2008-09-09T09:21:40.477-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='class'/><title type='text'>TA work</title><content type='html'>An instructor I had last fall emailed me over the summer asking me if I'd be interested in being a grader, since I did really will in the &lt;a href="http://www.epp.jhu.edu/course-homepages/viewpage.php?homepage_id=2903"&gt;class&lt;/a&gt; when I took it.  When I replied that I'd be interested, he added that I could contribute to a lecture if I liked.&lt;br /&gt;&lt;br /&gt;Naturally, I'm really stoked.  I've decided to do a presentation on why client-side security is unenforceable.  It will include a demo showing how you can trivially decompile a Java program, modify, and recompile it to exploit a flawed architecture where trust is placed in the client.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5508069880665417003?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5508069880665417003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5508069880665417003' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5508069880665417003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5508069880665417003'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/09/ta-work.html' title='TA work'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-4779291016506172307</id><published>2008-09-03T20:22:00.002-04:00</published><updated>2008-09-03T20:24:20.180-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='class'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Enterprise Java class</title><content type='html'>I started one of my two classes this semester--Enterprise Computing with Java.  It's basically going to deal with a variety of Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;EE&lt;/span&gt; technologies.  The instructor said to expect an average of about 15 hour/week, with around 20-30 hours some weeks, so this is going to be a lot of work.  My head is already spinning with all the Java &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;EE&lt;/span&gt; acronyms from the first lecture.&lt;br /&gt;&lt;br /&gt;Between this class, my Java Security class (starting next week), the TA work I'm doing, and my real job, I guess I'll get some sleep in December, when the semester ends.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-4779291016506172307?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/4779291016506172307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=4779291016506172307' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/4779291016506172307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/4779291016506172307'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/09/enterprise-java-class.html' title='Enterprise Java class'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-7508313009267563237</id><published>2008-08-29T11:23:00.004-04:00</published><updated>2008-08-29T14:49:25.428-04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='ldap'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Upgrade nfs/ldap server to Ubuntu 8.04</title><content type='html'>I finally got around to upgrading my NFS/OpenLDAP/Samba/postfix/&lt;a href="http://www.slimdevices.com/"&gt;Squeezebox&lt;/a&gt; and OpenVPN servers from Ubuntu 6.06 to 8.04.  I wanted to stay with the Long Term Support (LTS) release so I skipped the intervening releases.&lt;br /&gt;&lt;br /&gt;Ubuntu supports an in-place upgrade that, in the past, has worked quite well on my desktops.  However the file server is the most critical system on my network, so I had to make sure I had the time to do it right and to roll back, if necessary.&lt;br /&gt;&lt;br /&gt;In order to give myself the option of backing, out, I booted the system from an Ubuntu disc and imaged the boot drive onto a spare hard drive.&lt;br /&gt;&lt;br /&gt;I performed the upgrade first on the OpenVPN server since its configuration is much simpler, and it is less critical to the infrastructure.  That upgrade went swimmingly, other than being prompted whether to replace or keep a number of config files.&lt;br /&gt;&lt;br /&gt;I then upgraded the file server.  Overall, it went much more smoothly than I anticipated, given how much manual configuration went into getting OpenLDAP, Samba, postfix, and NFS working and integrated.&lt;br /&gt;&lt;br /&gt;The upgrade procedure choked on some errant whitespace in slapd.conf and terminated prematurely.  As far as I can tell, though it did everything else it needed to do before bailing.  It probably skipped upgrading OpenLDAP when it failed, then tried again after it had done everything else.&lt;br /&gt;&lt;br /&gt;I also had a problem with a hard-coded device node in the fstab for my backup drive.  All hard drives how get /dev/sdX, so the boot drive is now /dev/sda, which is what the USB backup drive used to be.  Once I replaced that with a UUID instead of the now incorrect /dev/sda1, the system would again boot properly.&lt;br /&gt;&lt;br /&gt;A weird problem that cropped up was that the squeezecenter software could no longer find any music.  It turned out that the local squeezecenter user wasn't showing up as a member of the Domain Users ldap group and didn't have access to the mp3s directory.  After much investigation, I discovered a directive in ldap.conf that tells libnss which usernames to ignore.  After removing squeezecenter from that list, its group memberships then resolved correctly and the squeezecenter software could access the music again.&lt;br /&gt;&lt;br /&gt;So now my most important system is running the up-to-date Ubuntu 8.04.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-7508313009267563237?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/7508313009267563237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=7508313009267563237' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7508313009267563237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7508313009267563237'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/08/upgrade-nfsldap-server-to-ubuntu-804.html' title='Upgrade nfs/ldap server to Ubuntu 8.04'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-6258463147553410415</id><published>2008-08-29T11:14:00.003-04:00</published><updated>2008-08-29T11:19:13.396-04:00</updated><title type='text'>Back to the Blog</title><content type='html'>It's been a long time since I posted anything to this blog. I had mostly given up on it.  I think the problem is that I tried not to post anything that wasn't a well-researched, detailed, technical article.  As such, there was a lot of overhead involved in preparing posts, and I rarely did them.&lt;br /&gt;&lt;br /&gt;I'd like to get back into it, and try to post more often, so I'm going to try to make this more of a personal notebook of things that I think are interesting or want to remember for later.  I may end up being my only reader, but that's fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-6258463147553410415?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/6258463147553410415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=6258463147553410415' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/6258463147553410415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/6258463147553410415'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2008/08/back-to-blog.html' title='Back to the Blog'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-8788909907017349263</id><published>2007-04-06T08:18:00.001-04:00</published><updated>2007-04-06T08:18:53.620-04:00</updated><title type='text'>EMI Selling non-DRMed tracks on ITunes Music store</title><content type='html'>Apple and EMI have &lt;a href="http://origin.arstechnica.com/news.ars/post/20070402-emi-to-announced-drm-free-plans-tomorrow-reports.html"&gt;announced&lt;/a&gt; that tracks from EMI&amp;#39;s catalog will be available from the ITunes Music Store without DRM.&amp;nbsp; I must admit I never thought I would see this happen.&amp;nbsp; I think this marks the beginning of a big change in online media.&amp;nbsp; I think most people don&amp;#39;t really understand what DRM is or what they&amp;#39;re giving up by buying DRMed media.&amp;nbsp; I think that for most people, as long as the DRM is sufficiently unrestrictive, then it really doesn&amp;#39;t make any difference.&amp;nbsp; I have always been worried that in time, Big Content, would lull consumers into giving up their fair use rights little by little.&amp;nbsp; The reason this announcement is big is that, for the first time, a major label is tacitly admitting that DRMed media isn&amp;#39;t necessarily just as good as the unrestricted variety.&amp;nbsp; For the first time, some people will stop consider the possibility that DRM devalues media and is something they don&amp;#39;t want. &lt;br&gt;&lt;br&gt;I think this is big, but it&amp;#39;s just a start.&amp;nbsp; Notwithstanding the facts that you still require ITunes to buy the EMI tracks, and they are downloaded in Apple&amp;#39;s AAC, as opposed to the near-universal MP3, there is the larger complication that nobody really keeps up with what labels their artists are on and which of the Big Four the labels are associated with.&amp;nbsp; Look at the enormous  &lt;a href="http://www.riaa.com/about/members/"&gt;list&lt;/a&gt; of RIAA member labels.&amp;nbsp; The majority of those are affiliated with one or more of the Big Four.&amp;nbsp; Which ones are part of EMI?&amp;nbsp; Who knows?&amp;nbsp; It&amp;#39;s not that easy.&amp;nbsp; Check out  RIAARadar.com&amp;#39;s disputed labels &lt;a href="http://riaaradar.com/info.asp"&gt;list&lt;/a&gt;.&amp;nbsp; This is definitely nontrivial.&lt;br&gt;&lt;br&gt;Anyway, this is exciting news.&amp;nbsp; I can&amp;#39;t wait to see where it leads.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-8788909907017349263?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/8788909907017349263/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=8788909907017349263' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/8788909907017349263'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/8788909907017349263'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2007/04/emi-selling-non-drmed-tracks-on-itunes.html' title='EMI Selling non-DRMed tracks on ITunes Music store'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-6585540476092090937</id><published>2007-02-28T08:44:00.001-05:00</published><updated>2007-02-28T08:44:40.600-05:00</updated><title type='text'>ESR Gives up on Red Hat, Switches to Ubuntu</title><content type='html'>I meant to post this last week, when it would have been timely, but was having problems with my blogger account.&lt;br&gt;&lt;br&gt;Last week, Eric Raymond, author of the famous essay, &lt;a href="http://www.catb.org/%7Eesr/writings/cathedral-bazaar/cathedral-bazaar/"&gt; &lt;span style="text-decoration: underline;"&gt;&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;The Cathedral and the Bazaar&lt;/span&gt;&lt;/a&gt;, posted a &lt;a href="http://enterprise.linux.com/article.pl?sid=07/02/21/1340237"&gt;message&lt;/a&gt;  to several open-source mailing lists expressing his frustration with Red Hat Linux.&amp;nbsp; According to the post, he&amp;#39;s switching to my distribution of choice, &lt;a href="http://www.ubuntu.com"&gt;Ubuntu&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Personally, although Red Hat is among the most popular of distributions, I&amp;#39;ve been a bit frustrated with it for a long time.&amp;nbsp; For one thing they have a habit of maintaining their own forks of much of the software included in the distro.&amp;nbsp; In other words, they make changes to the upstream projects, such as Firefox or the Linux kernel, that make them unique to Red Hat.&amp;nbsp; It&amp;#39;s not that they don&amp;#39;t make the changes available--they do, and they&amp;#39;re required to do so under those projects&amp;#39; respective licenses.&amp;nbsp; It&amp;#39;s just that the software you get with Red Hat exhibits behaviors, sometimes bugs, that are unique to Red Hat.&amp;nbsp; Ubuntu makes changes to the software they package as well, but they don&amp;#39;t generally maintain separate forks.&amp;nbsp; They generally get their changes merged into the upstream project. &lt;br&gt;&lt;br&gt;An example is the Firefox web browser.&amp;nbsp; For the longest time, the version of Firefox that shipped with Fedora Core (Red Hat&amp;#39;s unsupported community distribution) was compiled with Javascript 1.4, which broke websites that needed Javascript  1.5.&amp;nbsp; However if you downloaded the exact same version of Firefox directly from the Firefox website, it came with Javascript 1.5.&amp;nbsp; Why was it necessary to build Firefox differently than the way it comes from the upstream project? &lt;br&gt;&lt;br&gt;Another thing that Red Hat does is include a lot of configuration utilities that ease system administration by automating the generation of config files for various services.&amp;nbsp; However, when editing those same files by hand, you frequently are greeted with &amp;quot;This file was generated by the such-and-such utility.&amp;nbsp; Do not edit.&amp;quot;&amp;nbsp; Easing the tedium of hand configuring system services is one thing.&amp;nbsp; But taking away the ability to hand configure services is another.&amp;nbsp; What happens when the utility won&amp;#39;t generate the configuration to do what you need.&amp;nbsp; If you hand-tune the config, then your changes will get clobbered the next time the utility is run.&amp;nbsp;  &lt;br&gt;&lt;br&gt;This is in addition to the fact that if you&amp;#39;re coming from another distribution, and you expect to edit a config file which is in approximately the same place on every system, on Red Hat, you can&amp;#39;t do it--you have to learn some tool that exists only on Red Hat.&amp;nbsp; What good does it do to have a standardized configuration file in a standardized place, if you can&amp;#39;t edit it in a standardized way? &lt;br&gt;&lt;br&gt;In general I became frustrated by too many things done in the &amp;quot;Red Hat&amp;quot; way, that, once learned, are not useful or relevant on any other system.&lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-6585540476092090937?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/6585540476092090937/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=6585540476092090937' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/6585540476092090937'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/6585540476092090937'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2007/02/esr-gives-up-on-red-hat-switches-to.html' title='ESR Gives up on Red Hat, Switches to Ubuntu'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-5264942363869140436</id><published>2007-02-27T14:48:00.001-05:00</published><updated>2007-02-27T16:32:59.028-05:00</updated><title type='text'>Perl Program to Check for IP Address Change</title><content type='html'>My parents' ISP, BellSouth (now also known as &lt;a href="http://www.lilytomlin.com/video/Ernestine/SNL_1976/SNL_1976.html" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"&gt;AT&amp;T&lt;/a&gt;), has had the habit recently of frequently resetting their DSL connection, which results in service interruption as well as a new IP address.  One weekend, I noticed the IP address changing several times per hour.  I wanted a way of checking the IP address for changes, and logging it, so that I would be able to observe the frequency over time that this happens.&lt;br /&gt;&lt;br /&gt;To solve this problem, I wrote a Perl program that I could run from my own network, that would do the checking, and if the address changes, write the new address to a log.  As a bonus I decided to have the program send me an email notification of the change.&lt;br /&gt;&lt;br /&gt;I have my parents' computer registered under a dynamic DNS hostname which is a free service from &lt;a href="http://www.dyndns.com/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"&gt;DynDNS.com &lt;/a&gt;.  There are other, similar services, but I've been using DynDNS.com for about seven years, and I like them a lot.  There are lots of clients that will automatically update your IP address with DynDNS.  Many residential NAT routers, such as the one my parents use, have this functionality built in.  Every time their connection is reset, the built-in dynamic DNS client on their router detects the reset, and updates the new IP address.&lt;br /&gt;&lt;br /&gt;The dynamic hostname gives me something to do lookups against, even when the IP address has changed.&lt;br /&gt;&lt;br /&gt;The script follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/usr/bin/perl&lt;br /&gt;&lt;br /&gt;use Fcntl;&lt;br /&gt;use Tie::File;&lt;br /&gt;use Socket;&lt;br /&gt;use Mail::Mailer;&lt;br /&gt;my $name = "hostname.tocheck.com";&lt;br /&gt;my $to_address='to_address@gmail.com,another_address@mail.com';&lt;br /&gt;my $from_address='from_address@mail.com';&lt;br /&gt;my $subject="$name IP Address Change";&lt;br /&gt;my $message_body;&lt;br /&gt;my $logpath;&lt;br /&gt;my $logfile = "hostname.log";&lt;br /&gt;my $oldip;&lt;br /&gt;#Uncomment to turn on additional output&lt;br /&gt;#my $DEBUG=1;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#Subroutine to set (and create if necessary) #&lt;br /&gt;#the log path.                               #&lt;br /&gt;##############################################&lt;br /&gt;sub setLogPath{&lt;br /&gt;       if ($&gt; != 0){&lt;br /&gt;               print "About to set logpath to $ENV{'HOME'}/log\n" unless (!$DEBUG);&lt;br /&gt;               defined($ENV{'HOME'}) or die "Can't set logdirectory: I don't know where HOME is!\n";&lt;br /&gt;               $logpath="$ENV{'HOME'}/log";&lt;br /&gt;               if(! -d $logpath){&lt;br /&gt;                       mkdir($logpath) or die "Can't create $logpath: $!\n";&lt;br /&gt;               }&lt;br /&gt;       } else {&lt;br /&gt;               $logpath="/var/log";&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#Read the log file and                       #&lt;br /&gt;#get the last IP written.                    #&lt;br /&gt;##############################################&lt;br /&gt;sub getOldIp {&lt;br /&gt;       my @fields = split /\s+/,$iplog[-1]; #split the last line of the file on whitespace.&lt;br /&gt;       my $ip = $fields[-1]; #ip is the last field, whether there's 1 field or many&lt;br /&gt;       return $ip&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#Do DNS resolution to get the IP address as  #&lt;br /&gt;#a number.  Only if resoltion was            #&lt;br /&gt;#successful, convert the number to a         #&lt;br /&gt;#dotted-quad string.                         #&lt;br /&gt;##############################################&lt;br /&gt;sub getNewIp {&lt;br /&gt;       my $ip;&lt;br /&gt;       my $netip = inet_aton($name);&lt;br /&gt;       if (defined($netip)){&lt;br /&gt;               $ip = inet_ntoa($netip);&lt;br /&gt;       }&lt;br /&gt;       return $ip;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#If getNewIp() was successful (i.e. newip is #&lt;br /&gt;#defined), compare newip to oldip. return 1  #&lt;br /&gt;#if the different, 0 if the same, -1 if      #&lt;br /&gt;#newip is undefined.                         #&lt;br /&gt;##############################################&lt;br /&gt;sub checkIp{&lt;br /&gt;       if (!defined($newip)){&lt;br /&gt;               return -1;&lt;br /&gt;       } elsif ($newip ne $oldip){&lt;br /&gt;               return 1;&lt;br /&gt;       } else {&lt;br /&gt;               return 0;&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#Get the current UTC, and parse out in       #&lt;br /&gt;#defined), compare newip to oldip. return 1  #&lt;br /&gt;#if the different, 0 if the same, -1 if      #&lt;br /&gt;#newip is undefined.                         #&lt;br /&gt;##############################################&lt;br /&gt;sub doTimeStamp{&lt;br /&gt;       ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = gmtime();&lt;br /&gt;       $year=1900+$yearOffset;&lt;br /&gt;       $month=$month+1;&lt;br /&gt;       my $timeStamp=sprintf("%d%02d%02d %02d:%02d:%02d\tUTC",$year,$month,$dayOfMonth,$hour,$minute,$second);&lt;br /&gt;       return $timeStamp;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#Build and send the email using Perl's slick #&lt;br /&gt;#Mailer class.                               #&lt;br /&gt;##############################################&lt;br /&gt;sub message{&lt;br /&gt;       $message_body="The IP Address for $name has changed.\nOld address:\t$oldip\nNew address:\t$newip\n";&lt;br /&gt;       $mailer = Mail::Mailer-&gt;new("sendmail");&lt;br /&gt;       $mailer-&gt;open({ From    =&gt; $from_address,&lt;br /&gt;                       To      =&gt; $to_address,&lt;br /&gt;                       Subject =&gt; $subject,&lt;br /&gt;                    })&lt;br /&gt;               or die "Can't open: $!\n";&lt;br /&gt;       print $mailer $message_body;&lt;br /&gt;       $mailer-&gt;close();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##############################################&lt;br /&gt;#Main program:                               #&lt;br /&gt;#-Set the logpath                            #&lt;br /&gt;#-open the logfile                           #&lt;br /&gt;#-Get the last known IP address              #&lt;br /&gt;#-Get the current IP address                 #&lt;br /&gt;#-Compare the last and current addresses     #&lt;br /&gt;#-If there was a change, log the change and  #&lt;br /&gt;#  Send an email                             #&lt;br /&gt;#-If couldn't resolve hostname, display error#&lt;br /&gt;#-Else do nothing                            #&lt;br /&gt;#-Close the logfile                          #&lt;br /&gt;#-Exit with $check status                    #&lt;br /&gt;##############################################&lt;br /&gt;setLogPath();&lt;br /&gt;print "Opening $logpath/$logfile\n" unless(!$DEBUG);&lt;br /&gt;tie @iplog, Tie::File, "$logpath/$logfile" or die "Couldn't open $logpath/$logfile : $!\n";&lt;br /&gt;$oldip = getOldIp();&lt;br /&gt;print "Old IP is $oldip.\n" unless(!$DEBUG);&lt;br /&gt;$newip = getNewIp();&lt;br /&gt;my $check = checkIp();&lt;br /&gt;if ($check == 1){&lt;br /&gt;       $timeStamp=doTimeStamp();&lt;br /&gt;       $iplog[ $#iplog +1 ] = "$timeStamp\t$newip";  #add a new line to the end of the file&lt;br /&gt;       &amp;message;&lt;br /&gt;} elsif ($check == -1){&lt;br /&gt;               printf (STDERR "Couldn't resolve %s.\n", $name);&lt;br /&gt;}&lt;br /&gt;untie(@iplog);&lt;br /&gt;&lt;br /&gt;exit $check;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This past weekend the script logged over 80 IP address changes on Saturday.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-5264942363869140436?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/5264942363869140436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=5264942363869140436' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5264942363869140436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/5264942363869140436'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2007/02/perl-program-to-check-for-ip-address.html' title='Perl Program to Check for IP Address Change'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-116336049812068056</id><published>2006-12-01T00:55:00.000-05:00</published><updated>2006-12-02T00:56:35.361-05:00</updated><title type='text'>Christmas Wish List</title><content type='html'>Note:  Several links were wrong.  Hopefully they are now fixed.&lt;br /&gt;&lt;br /&gt;My &lt;del&gt;friends&lt;/del&gt; &lt;del&gt;family&lt;/del&gt; &lt;ins&gt;mom&lt;/ins&gt; has been asking about my wish list, so here it is.  Each item is linked to where it may be found online.  The usual caveat applies--people shopping from this list should deconflict with each other.  Of course gift cards can be duplicated!&lt;br /&gt;&lt;br /&gt;Readers should feel free to post a link to their own wishlists in the comments, or in an email.&lt;br /&gt;Be sure to check back for updates.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://store.2600.com/subscriptions.html"&gt;Subscription&lt;/a&gt; to 2600 magazine&lt;br /&gt;(lifetime subscription would be nice:-) &lt;/li&gt;&lt;li&gt;Harmony 688 programmable &lt;a href="http://www.newegg.com/Product/Product.asp?Item=N82E16880100709"&gt;universal remote&lt;/a&gt;:&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.bananarepublic.com/browse/product.do?cid=10835&amp;pid=375296"&gt;Messenger bag &lt;/a&gt; from Banana Republic&lt;/li&gt;&lt;li&gt;Death Cab for Cutie, "&lt;a href="http://www.amazon.com/Plans-Death-Cab-Cutie/dp/B000AADYRQ/sr=8-1/qid=1163374128/ref=pd_bbs_sr_1/104-5733560-6163959?ie=UTF8&amp;amp;s=music"&gt;Plans&lt;/a&gt;"&lt;/li&gt;&lt;li&gt;"&lt;a href="http://www.amazon.com/She-Wants-Revenge/dp/B000BCE8VE/sr=8-1/qid=1164305795/ref=pd_bbs_sr_1/104-6514127-6755936?ie=UTF8&amp;s=music"&gt;She Wants Revenge&lt;/a&gt;"&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Garden State &lt;a href="http://www.amazon.com/Garden-State-Various-Artists/dp/B0002J58LK/sr=8-1/qid=1165038441/ref=pd_bbs_sr_1/104-6514127-6755936?ie=UTF8&amp;amp;s=music"&gt;soundtrack&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Mac-OS-Tiger-Unix-Geeks/dp/0596009127/sr=8-1/qid=1163533384/ref=pd_bbs_sr_1/104-5733560-6163959?ie=UTF8&amp;s=books"&gt; Mac OS X Tiger for Unix Geeks&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Perl-Cookbook-Second-Tom-Christiansen/dp/0596003137/sr=8-1/qid=1165038760/ref=sr_1_1/104-6514127-6755936?ie=UTF8&amp;amp;s=books"&gt;The Perl Cookbook&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Perl-Hacks-Programming-Debugging-Surviving/dp/0596526741/sr=1-1/qid=1165038848/ref=pd_bbs_sr_1/104-6514127-6755936?ie=UTF8&amp;s=books"&gt;Perl Hacks&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/Wicked-Cool-Perl-Scripts-Difficult/dp/1593270623/sr=8-1/qid=1163374781/ref=pd_bbs_sr_1/104-5733560-6163959?ie=UTF8&amp;amp;s=books"&gt;Wicked Cool Perl Scripts&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Transformers Season Two Boxed Set, &lt;a href="http://www.amazon.com/Transformers-Season-Two-Boxed-Part/dp/B00006L9PL/sr=8-1/qid=1163358728/ref=sr_1_1/104-5733560-6163959?ie=UTF8&amp;s=dvd"&gt;Part 1 &lt;/a&gt;&lt;br /&gt;and&lt;/li&gt;&lt;li&gt;Transformers Season Two Boxed Set, &lt;a href="http://www.amazon.com/Transformers-Season-Two-Boxed-Part/dp/B00008RH31/sr=8-2/qid=1163358728/ref=sr_1_2/104-5733560-6163959?ie=UTF8&amp;amp;s=dvd"&gt;Part 2&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;Gift cards from:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.bananarepublic.com/browse/category.do?cid=25683&amp;amp;amp;amp;amp;amp;mlink=5817,248387,9&amp;clink=248387"&gt;Banana Republic&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.gap.com/customerService/info.do?cid=2116&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;mlink=5058,644743,6&amp;clink=644743"&gt; The Gap&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.gap.com/customerService/info.do?cid=2116&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;mlink=5058,644743,6&amp;clink=644743"&gt;&lt;/a&gt;&lt;a href="https://secure.newegg.com/NewVersion/GiftCertificate/GiftCertificate.asp"&gt;Newegg.com&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.jcrew.com/catalog/giftcard.jhtml"&gt;J. Crew&lt;/a&gt;&lt;a href="http://www.gap.com/customerService/info.do?cid=2116&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;mlink=5058,644743,6&amp;amp;clink=644743"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-116336049812068056?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/116336049812068056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=116336049812068056' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116336049812068056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116336049812068056'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/11/christmas-wish-list.html' title='Christmas Wish List'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-7914060165332761698</id><published>2006-11-28T13:01:00.000-05:00</published><updated>2006-11-28T19:58:55.338-05:00</updated><title type='text'>Play an mp3 over SSH</title><content type='html'>Secure Shell really is the coolest thing since sliced bread.&amp;nbsp;&amp;nbsp;Well, actually it's probably cooler.&amp;nbsp;&amp;nbsp; If you're not already familiar with SSH, then you probably are unaware of all the crazy things you can use it for.&amp;nbsp; For example, you can burn a CD to a remote computer over SSH. &lt;br&gt;&lt;br&gt;You can also play an mp3 (or several mp3s) over SSH.&amp;nbsp; Here's how&lt;br&gt;&lt;br&gt;When you ssh (lowercase refers to the actual Unix command) into a machine, it usually is done like this:&lt;br&gt;&lt;br&gt;&lt;span style="font-family: courier new,monospace;"&gt; ssh &lt;a href="mailto:uidzero@machinename.com"&gt;uidzero@machinename.com&lt;/a&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;This connects you to the machine, and, after authenticating as the user, 'uidzero',&amp;nbsp; executes the user's default shell, usually '/bin/sh'.&amp;nbsp; However, you can have have it execute some other command by specifying the command at the end.&amp;nbsp; For example,  &lt;br&gt;&lt;br&gt;&lt;span style="font-family: courier new,monospace;"&gt;ssh &lt;a href="mailto:uidzero@machinename.com"&gt;uidzero@machinename.com&lt;/a&gt; 'cat /etc/passwd'&lt;/span&gt;&lt;br&gt; &lt;br&gt;would display the contents of the remote machine's passwd file (/etc/passwd is world readable).&lt;br&gt;&lt;br&gt;So to play an mp3 file, we need to cat the contents of the file back across the ssh connection, like we just did with /etc/passwd. &lt;br&gt;&lt;br&gt;However, we also need an mp3 playback program that can play from standard in.&amp;nbsp; 'mpg123' is an ideal candidate.&amp;nbsp; By specifying a dash, '-', you can tell it to play from standard input.&amp;nbsp; You can try it like this,&lt;br&gt; &lt;br&gt;&lt;span style="font-family: courier new,monospace;"&gt;cat file.mp3 | mpg123 -&lt;br&gt;&lt;/span&gt;&lt;br&gt;This reads the mp3 in a stream of bytes and sends them to the standard input of the mpg123 program.&lt;br&gt;&lt;br&gt;Now to put it together, we ssh into the remote machine, catting the mp3 we want, and piping the output of the ssh command to our local mpg123's standard input. &lt;br&gt;&lt;br&gt;&lt;span style="font-family: courier new,monospace;"&gt;ssh &lt;a href="mailto:uidzero@machinename.com"&gt;uidzero@machinename.com&lt;/a&gt; 'cat /mp3s/song.mp3' | mpg123 -&lt;/span&gt;&lt;br&gt;&lt;br&gt;Okay, so there's probably not much reason to do this particular thing, but it's easy to see the the flexibility of SSH.&amp;nbsp; Combined with Unix's ability to send and receive bytes to and from anywhere you choose, SSH is a veritable Swiss Army Knife. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-7914060165332761698?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/7914060165332761698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=7914060165332761698' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7914060165332761698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/7914060165332761698'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/11/play-mp3-over-ssh.html' title='Play an mp3 over SSH'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-1274709560494099288</id><published>2006-11-18T11:03:00.001-05:00</published><updated>2006-12-05T14:11:10.745-05:00</updated><title type='text'>MacBook</title><content type='html'>update #1: somebody read my blog&lt;br /&gt;udpate #2: I added a link (inline) to the website where the tun/tap kernel extensions can be found for use with OpenVPN&lt;br /&gt;&lt;br /&gt;I just got an apple &lt;a href="http://www.apple.com/macbook/macbook.html"&gt;MacBook&lt;/a&gt; (thank goodness for &lt;a href="http://creditcards.com/low-interest.php"&gt;0% credit cards&lt;/a&gt; and &lt;a href="http://www.apple.com/education/store"&gt; educational discount&lt;/a&gt;).  I opted for the black model, and upgraded from 512mb ram to 1gb (this was an option that was cheaper to include on the order than to do myself).  I had been holding off ordering it since the MacBook pros had just been updated, and there were rumors the MacBooks might get similar treatment before year end.  When a few weeks went by with no sign of updates, I took the dive and placed the order. That was a Monday.  On Wednesday, Apple introduced new MacBooks with a whole slew of updates including 2ghz Core 2 Duo, 1gb RAM, 120gb hard drive (up from 80) in the black model.  I called Apple customer service to see if there was a chance they would upgrade my order to the new model since it had not yet shipped.  They confirmed that the order was already upgraded (allegedly prior to my calling).  Woohoo!  My timing couldn't be more perfect.  Since 1gb of RAM was now part of the base configuration, my order was now $100 less!&lt;br /&gt;&lt;br /&gt;Well a week after placing the original order, my MacBook finally shipped, and I received it this past Tuesday.  Of course the first thing I wanted to do was get connected to my wireless and surf from the couch.  Of course, until I had the new machine configured to connect to  &lt;a href="http://shadow-file.blogspot.com/2006/08/openvpn.html"&gt;OpenVPN&lt;/a&gt;,  so I had to disable all the firewall rules on my router.  I set the WEP key to the wireless and immediately connected.  Instantly something was wrong--the connection was very stuttery.  It would work then not work, and nothing I could think of seemed to help.  I continued troubleshooting the rest of the evening, before finally giving up for the rest of the night.  The next day, some googling revealed that others were having similar compatibility problems with the same wireless AP that I have--the ancient D-Link DI-614+.  I was prepared to bite the bullet and order a new(er) Linksys wireless router, which would  &lt;span style="font-style: italic;"&gt;finally&lt;/span&gt; bring an end to the reign of 802.11b in our house, and usher in a "new" era of higher-speed 802.11g.  I didn't want to spend the money, but the prospect of getting  802.11g, made it easier to swallow.  Before placing the order, I did a last bit of troubleshooting.  I wanted to see if there were any settings on the D-Link wireless router that would make a difference.  The first thing I tried was to turn of "4x-mode."  I wasn't exactly sure what this was, but I was certain it had something to do with enhanced performance if you had all D-Link hardware, which I didn't.  This instantly did the trick (I may have changed one or more other settings at the same time--I'm not sure)!  Oh well, so much for coming into the New Millenium--I'm still on pokey  802.11b, but it works, and is more than sufficient for simple web browsing &amp; email.&lt;br /&gt;&lt;br /&gt;The other issue that cropped up was trouble shooting static DHCP assignment.  This is so that every time the machine connects to the network, it should be assigned the same IP address, based on it's hardware address.  I have the dynamic pool (pool from which non-static addresses are randomly doled out) restricted down to exactly one address.  Every time I would lease an address it would be the single dynamic address, not the static address which I had assigned.  Incidentally, I was troubleshooting this issue simultaneously while dealing with the flaky wireless issue, multiplying my frustration.  The next day, it occurred to me what I had forgotten.  The wireless network is on a different subnet from the wired.  I was assigning the wireless interface on the MacBook a static address from the wrong subnet.   Of course the DHCP server was smart enough not to reply to a request with an address from the wrong subnet, so it could only give out an address from the dynamic pool.  Once I fixed this, and then restarted the DHCP server, everything was fine.  I was relieved.&lt;br /&gt;&lt;br /&gt;OpenVPN was pretty straightforward, but it's a bit disappointing that it's not as well supported for OS X as under Linux and other Unix OSes.  There are only a handful of people developing and maintaining the various components required to use OpenVPN.  The first thing I discovered was a package called  &lt;a href="http://www.tunnelblick.net/"&gt;Tunnelblick&lt;/a&gt;, which includes the Tunnelblick GUI, as well as OpenVPN, the necessary kernel extensions (like Linux kernel modules--think "drivers") to configure the network tunnel.  Unfortunately the kernel extensions that came with Tunnelblick wouldn't load--evidently due to incompatibility with the very latest version of OS X (10.4.8).  I search around and found the &lt;a href="http://www-user.rhrk.uni-kl.de/%7Enissler/tuntap/"&gt;website&lt;/a&gt; for the author of the kernel extensions, where I found a new, "experimental" version of the drivers that allegedly is compatible.  The website had an Ominous warning:&lt;br /&gt;&lt;blockquote style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;" class="gmail_quote"&gt;This might crash your machine! If it does, don't blame me. I had some crashes testing the   new code when I did lots of loading/unloading cycles. It seems to work reasonably well once it    is loaded, so don't be to scared. &lt;/blockquote&gt;Wow.  Scary.  With trepidation, I installed and loaded the "experimental" kernel extensions.  So far they've been working flawlessly.  I've also been using the release candidate of Tunnelblick  3.0.  It's a bit nicer, attempts to configure your DNS, and shows log output from the OpenVPN connection.&lt;br /&gt;&lt;br /&gt;So I've had the MacBook for five days, and so far, I love it.  One thing is for sure; Apple knows how to get the aesthetics right.  This is a beautiful, elegant machine.  It may not seem like a big deal, but having used it for a few days, I realize how much difference that last "5%" makes when it comes to the physical design.  It did take some initial tweaking to get things just like I want, and there are still some things that I  can't configure to my liking.  However unlike Windows, when you can't configure something the way you want it, it doesn't feel like an oversight--it feels like Apple has decided that you don't need it that way.&lt;br /&gt;&lt;br /&gt;I immediately installed &lt;a href="http://www.getfirefox.com/"&gt;Firefox&lt;/a&gt; and &lt;a href="http://www.getthunderbird.com/"&gt;Thunderbird&lt;/a&gt;, as well as &lt;a href="http://enigmail.mozdev.org/"&gt;enigmail &lt;/a&gt; (Thunderbird really should come with this) for Thunderbird,  and &lt;a href="http://macgpg.sourceforge.net/"&gt;gpg&lt;/a&gt; (open source PGP), and a slew of other things.  I have to say the state of &lt;a href="http://www.openoffice.org/"&gt; OpenOffice&lt;/a&gt; on OS X is just sad.  It doesn't integrade with the OS at all.  It feels like 1998 Solaris.  I also installed MS Office 2004.  Not available in native format for Intel Macs, it runs emulated in Rosetta.  I am amazed at how fast it is.&lt;br /&gt;&lt;br /&gt;For the past few years, I've been using Linux almost exclusively, and I understand how it works on a fairly technical level.  It drives me crazy to be using an OS where I don't understand the underlying mechanics of how things work.  OS X has Unix underpinnings, which is nice, and I'll definitely be  &lt;a href="http://www.amazon.com/Mac-OS-Tiger-Unix-Geeks/dp/0596009127/sr=8-1/qid=1163863716/ref=pd_bbs_sr_1/104-6514127-6755936?ie=UTF8&amp;amp;s=books"&gt;learning &lt;/a&gt;about that, but there are a lot of differences from Linux or other Unixes.  I plan on installing Linux and probably Windows, for a triple boot.  However, I plan on traveling with it over Thanksgiving, so I don't want to break it just yet.&lt;br /&gt;&lt;br /&gt;Anyway, I love the MacBook.  It is beautiful, and competitively priced to similarly spec'd PCs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-1274709560494099288?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/1274709560494099288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=1274709560494099288' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1274709560494099288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/1274709560494099288'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/11/macbook.html' title='MacBook'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-116118220264462545</id><published>2006-10-18T10:36:00.000-04:00</published><updated>2006-11-12T18:22:29.624-05:00</updated><title type='text'>New Car, No Dipstick, WTF?</title><content type='html'>&lt;span class="gmail_quote"&gt;&lt;/span&gt;Our new car (which we've had since August) has no dipstick.&amp;nbsp; That's right, there's no dipstick to check the oil level.&amp;nbsp; Rather you flip through the options in the trip computer, and, assuming the engine is running and you've just driven at least  6.5 miles, the oil level is displayed on-screen in the instrument cluster.&amp;nbsp; When we test drove the car, the salesman highlighted that messy oil-checking was not necessary--the computer would let you know if anything is amiss.&amp;nbsp; When we picked up the car and received an orientation of every little feature, again, we were shown how there was nothing to do under the hood and that all would be seen to by the computer.&amp;nbsp; I was skeptical, but I decided to reserve judgement.&amp;nbsp; Perhaps they really did get this down, and everything really works as promised. &lt;br&gt;&lt;br&gt;Well, fast forward to this past weekend.&amp;nbsp; The computer just alerted us that the engine was low on oil by at least a quart. With 2800 miles on it, I thought this very odd but dutifully added the oil anyway. Then the computer still said it needed another quart. Now I was really suspicious. Either it was really burning oil, or the computer was wrong and I had just added oil when it didn't need it.&amp;nbsp; Either explanation is bad.&amp;nbsp; Without a dipstick, there was no way to tell. Afraid to drive it in case of over-full oil, I left it parked the rest of the weekend until the dealer was open again on Monday. Keeping the car two days, they told me the oil level sensor had failed and was being replaced.&lt;br&gt;&lt;br&gt;So now I am prepared to pass judgement.&amp;nbsp; The &amp;quot;no dipstick&amp;quot; idea is dumb.&amp;nbsp; I am almost certain this is a marketing decision rather than an engineering one.&amp;nbsp;&amp;nbsp; Dipsticks are reliable.&amp;nbsp; Dipsticks don't have integer overflows, bounds-checking violations, or kernel panics.&amp;nbsp; Computers do.&amp;nbsp; No one ever says &amp;quot;I don't know how much oil I have because I can't get a reliable reading from the damn dipstick.&amp;quot;&amp;nbsp; Cleverness for its own sake is almost never a good idea, and there is elegance in simplicity. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-116118220264462545?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/116118220264462545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=116118220264462545' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116118220264462545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116118220264462545'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/10/new-car-no-dipstick-wtf.html' title='New Car, No Dipstick, WTF?'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-116109536530979730</id><published>2006-10-17T10:29:00.000-04:00</published><updated>2006-11-12T18:22:29.446-05:00</updated><title type='text'>Server progress: OpenLDAP</title><content type='html'>Making good progress on OpenLDAP &amp;amp; Samba.&amp;nbsp;&amp;nbsp;I've got them both configured.&amp;nbsp;&amp;nbsp;I used the &lt;a href="http://sourceforge.net/projects/smbldap-tools/"&gt;smbldap-tools&lt;/a&gt; scripts to add a user and set a password.&amp;nbsp; I then was able to log in with that user. Home directory was created.&amp;nbsp; Checking the id showed proper User ID as well as group membership.&amp;nbsp; Removing the user successfully removed home directory as well. &lt;br&gt;&lt;br&gt;I haven't yet test this from the windows side though.&lt;br&gt;&lt;br&gt;&lt;span style="text-decoration: underline;"&gt;Todo:&lt;/span&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;Add a machine to the domain (should create machine account automatically)&lt;/li&gt;&lt;li&gt;Add log on from windows machine &lt;/li&gt;&lt;li&gt;TLS for encrypted LDAP communication&lt;/li&gt;&lt;li&gt;Migrate data from old server&lt;/li&gt;&lt;li&gt;Migrate user profiles from old server&lt;br&gt;&lt;/li&gt;&lt;/ul&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-116109536530979730?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/116109536530979730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=116109536530979730' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116109536530979730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116109536530979730'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/10/server-progress-openldap.html' title='Server progress: OpenLDAP'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-116101039780398583</id><published>2006-10-16T10:53:00.000-04:00</published><updated>2006-11-12T18:22:29.360-05:00</updated><title type='text'>Battlestar Galactica Season 3 Premiere</title><content type='html'>I finally got around to watching the premiere episode of the third season of BSG last night.&amp;nbsp; Actually, I didn't watch all of it--it is 2 hours, and it was a school night.&amp;nbsp; Not sure what to say other than this show just gets better and better.&amp;nbsp; The Ron Moore continues to take a bad situation and make it worse.&amp;nbsp; Things are really a mess right now for the human race. &lt;br&gt;&lt;br&gt;Regarding aesthetics, the show has the same grittiness, the same great cinematography, and great musical score we've come to expect from the series.&amp;nbsp; The story continues to blur the distinction between good and evil in contrast to the original series where the Bad Guy consisted of shiny robots bent on killing humans. &lt;br&gt;&lt;br&gt;A friend of mine blogged about the parallels he sees in the the show relative to the Iraq war, and about how insurgents are just fighting against an oppressive occupation which is trying to force a way of life on an unreceptive people.&amp;nbsp; I immediately took issue with this assessment--my friend is a Raging Liberal, after all, and it is natural to see things that support your own viewpoint, and to overlook the things that don't.&amp;nbsp; However, after having seen (most of) the season 3 premiere, I now admit that there are a number of parallels that writer-director Ron Moore has intentionally and carefully placed in plain view and spoon-feeds to the audience.&amp;nbsp; However, I feel that the Iraq war analogy really falls apart after just a bit of close scrutiny.&amp;nbsp; The Cylons came out of nowhere after not being heard of for many years and whooped the human race.&amp;nbsp; After reducing humans to mere thousands, the Cylons have subjugated the remaining few.&amp;nbsp;  &lt;br&gt;&lt;br&gt;By contrast, in the Real World, the US, after many years of isolationism despite being attacked over and over again, finally has taken action to bring an entire culture forward about 1,000 years into the 21st century.&amp;nbsp; This is entirely an act of self preservation.&amp;nbsp; You can only get your butt whooped for so long before you have to do something.&amp;nbsp; This is a problem that is not been solved before.&amp;nbsp; There is no right answer.&amp;nbsp; We chose to pick a country with whom we have been at war for 12 years, and turn it into a democracy.&amp;nbsp; No subjugation involved.&amp;nbsp; Just go vote and stop killing people--that's all we ask.&amp;nbsp; Check back in about 10 years to see how it turns out. &lt;br&gt;&lt;br&gt;So, I agree that there is an intended analogy between the show and the war in Iraq.&amp;nbsp; However, I think it is a flawed one.&amp;nbsp; I think, perhaps, that a better comparison would be the &lt;a href="http://en.wikipedia.org/wiki/Maquis_%2528World_War_II%2529"&gt; Maquis&lt;/a&gt;  during WWII, which fought the Nazis in occupied France (who, like Baltar, opted to surrender rather than fight).&lt;br&gt;&lt;br&gt;Anyway, political undertone or not, this is a great show, and I'm really looking forward to seeing what happens next.&amp;nbsp; I really don't see how things can get much worse. &lt;br&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-116101039780398583?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/116101039780398583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=116101039780398583' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116101039780398583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116101039780398583'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/10/battlestar-galactica-season-3-premiere.html' title='Battlestar Galactica Season 3 Premiere'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-116049298539355996</id><published>2006-10-10T11:09:00.000-04:00</published><updated>2006-11-12T18:22:29.278-05:00</updated><title type='text'>Server Problems &amp; More OpenVPN</title><content type='html'>Since I originally &lt;a href="http://shadow-file.blogspot.com/2006/08/openvpn.html"&gt;posted&lt;/a&gt; about OpenVPN, it has become a critical service for me.&amp;nbsp; Not only do I VPN home from work everyday, but I also VPN out of the wireless sandbox when I'm roaming ( i.e., surfing from the couch) around the house.&amp;nbsp; Naturally, the first service I implemented on the new server was OpenVPN.&amp;nbsp; Well, last Saturday, I was looking forward to making some progress on OpenLDAP and Samba, when the server started acting up.&amp;nbsp; It would lock up after running for only a few minutes.&amp;nbsp; After going through all the obvious troubleshooting, the problem only seemed to worsen.&amp;nbsp; Eventually the machine wouldn't even  &lt;a href="http://en.wikipedia.org/wiki/Power-on_self-test"&gt;POST&lt;/a&gt;, and I resigned to the reality that the thing had Shit the Bed.&amp;nbsp; I ordered a new motherboard (due today), and accepted the fact that I was now set back 4 more days plus $50. &lt;br&gt;&lt;br&gt;However, I still had problem of what to do about the OpenVPN server.&amp;nbsp; Well, I immediately scrambled to install OpenVPN on my desktop machine (seriously, I really can't live without OpenVPN).&amp;nbsp; I had to get the hard drive out of the server and hook it up, in order to get the VPN configuration file as well as the Certificate Authority, which I would need to create an SSL cert for the &amp;quot;temporary&amp;quot; server.&amp;nbsp; In addition I had to modify the firewall rules on my router to allow VPN traffic to the my desktop.&amp;nbsp; Anyway, the upside is that I'm getting good at generating SSL certs, and can do it in a matter of minutes.&amp;nbsp; This certainly will come in handy when I finally get back to OpenLDAP. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-116049298539355996?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/116049298539355996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=116049298539355996' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116049298539355996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116049298539355996'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/10/server-problems-more-openvpn.html' title='Server Problems &amp; More OpenVPN'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-116049171637655107</id><published>2006-10-10T10:48:00.000-04:00</published><updated>2006-11-12T18:22:29.201-05:00</updated><title type='text'>New Server</title><content type='html'>I'm in the process of building a new server to replace my aging Red Hat 9 Samba/NFS/misc server.&amp;nbsp;&amp;nbsp;Actually, not new hardware, but rather a new OS and new services.&amp;nbsp;&amp;nbsp;The plan is for it to be an OpenLDAP/Samba integration project, so that I can have common network-based authentication from Linux &amp;amp; Windows (and possibly Mac OS X) machines.&amp;nbsp;&amp;nbsp;Right now I can authenticate against Samba from Windows and have network shares, roaming profiles, etc.&amp;nbsp;&amp;nbsp;Linux accounts are all local, however.&amp;nbsp;&amp;nbsp;That is ghetto. &lt;br&gt;&lt;br&gt;So, the &amp;quot;new&amp;quot; server isn't on new hardware, so much as recycled hardware.&amp;nbsp;&amp;nbsp;The hardware that &lt;span style="font-style: italic;"&gt;is&lt;/span&gt; new consists of a 250Gb hard drive for shared &amp;amp; home directories plus two more&amp;nbsp; of the same (but in USB enclosures) for rotating backups, in addition to a 4U  &lt;a href="http://www.newegg.com/Product/Product.asp?Item=N82E16811219008"&gt;rackmount case&lt;/a&gt;.&amp;nbsp; Everything else is recycled.&amp;nbsp; The nice thing is a modern &lt;a href="http://www.ubuntu.com/news/606released"&gt;operating system&lt;/a&gt; that gets updates for 5 years. &lt;br&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-116049171637655107?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/116049171637655107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=116049171637655107' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116049171637655107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/116049171637655107'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/10/new-server.html' title='New Server'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-115678099261621779</id><published>2006-08-28T12:03:00.000-04:00</published><updated>2006-11-12T18:22:29.134-05:00</updated><title type='text'>OpenVPN</title><content type='html'>&lt;span class="gmail_quote"&gt;&lt;/span&gt;I have discovered the thing that shall replace sliced bread as the gold standard by which cool things are measured.&amp;nbsp;&amp;nbsp;That thing is &lt;a href="http://openvpn.net/" target="_blank" onclick="return top.js.OpenExtLink(window,event,this)"&gt; OpenVPN&lt;/a&gt;.&amp;nbsp; Basically, it is an open source VPN solution that lets you do virtual private networking using SSL for encryption. &lt;br&gt;&lt;div&gt;&lt;br&gt;For a while I have been looking for a solution that will let me tunnel my Internet traffic through my home network, when I'm out and about with my laptop, such as at hotels, etc.&amp;nbsp; This would allow me to surf the web, check email, etc without my traffic being intercepted by other people who may also have access to the network.&amp;nbsp; In the past, I have used secure shell (SSH) to tunnel web traffic to my home network.&amp;nbsp; That solution works fairly well, but it's a bit ghetto.&amp;nbsp; For one thing, it only secures your web traffic, and you have to manually configure your web browser to use a proxy server.&amp;nbsp; If you POP your email, that goes out unsecured.&amp;nbsp; And I won't bore you with and explanation of the problems with tunneling TCP over TCP. &lt;br&gt;&lt;br&gt;Anyway, when I connect to my OpenVPN server at home, it's just as if I've plugged right into my home network--right down to mounting NFS shares, printing to my printer (!), telnetting to my Tivo, streaming my mp3s.&amp;nbsp; It's just like being at home.&amp;nbsp; Plus it's all over SSL, so to anyone sniffing my traffic, all they see is SSL encrypted traffic destined to and originating from my home network.&amp;nbsp; The only limiting factor is that my the upstream on my home DSL line is 384k, so that is a bottleneck. &lt;br&gt;&lt;br&gt;Also, now I am finally able to lock down my wireless network.&amp;nbsp; When I'm at home, I just connect over the wireless to my OpenVPN server just as if I were out and about and everything going out over the air is now SSL encrypted.&amp;nbsp; By configuring my router's firewall rules to not trust the wireless subnet, except for OpenVPN traffic, anyone who is able to crack the WEP key and get on the wireless is in a sandbox and can't talk to anything since they don't have a certificate for the vpn. &lt;br&gt;&lt;br&gt;I'll try to post some details later, such as my firewall configuration and how I architected the network to secure the wireless.&amp;nbsp; At any rate, I'm very pleased with OpenVPN.&amp;nbsp; It really does what I need.&lt;br&gt;  &lt;/div&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-115678099261621779?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/115678099261621779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=115678099261621779' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/115678099261621779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/115678099261621779'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/08/openvpn.html' title='OpenVPN'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-115642046883805214</id><published>2006-08-24T07:38:00.008-04:00</published><updated>2010-11-19T07:48:25.511-05:00</updated><title type='text'>Execution on SPARC CPUs</title><content type='html'>Execution on SPARC CPUs&lt;br /&gt;&lt;br /&gt;As a followon to the &lt;a href="http://shadow-file.blogspot.com/2006/08/execution-on-intel-x86-cpus.html"&gt;x86 execution demo&lt;/a&gt;, I'd like to take a look at execution on SPARC CPUs.&lt;br /&gt;&lt;br /&gt;If &lt;a href="http://en.wikipedia.org/wiki/Berkeley_RISC" target="_blank"&gt;Berkley RISC&lt;/a&gt; architecture can be said to be the textbook definition of RISC, then SPARC CPUs are a textbook implementation.  This is because the SPARC architecuture is heavily influenced by Berkeley RISC I &amp;amp; II.&lt;br /&gt;&lt;br /&gt;In this demo we'll take a look at the same simple adder program from the x86 demo.  This is to establish a context in which we can compare the essentials of x86 and SPARC execution.  However, it should be noted that the adder program is extremely simplistic.  As such, there are a number of characteristics of the SPARC architecture which are worthy of analysis, which will not be exposed during the course of this demo.  I'll try to highlight a few of these in the conclusion.&lt;br /&gt;&lt;br /&gt;Before we get started, a general introduction of how things work with SPARC is in order.&lt;br /&gt;&lt;br /&gt;Addressing &amp;amp; Memory access:&lt;br /&gt;On the SPARC, there are only two addressing modes: Register-indirect and immediate.  An operand is either loaded from the effective address already stored in a register, or it is included right in the instruction itself.  There is no concept of direct addressing on SPARC.  Also, there are only two types of memory accesses: Load and Store.  Data is loaded from memory into registers, or stored from registers into memory.  In fact, RISC architectures are sometimes referred to as load/store architectures.&lt;br /&gt;&lt;br /&gt;Registers:&lt;br /&gt;In contrast to the x86 architecture we looked at previously, which has only six general-purpose registers (only four if you don't count the index registers), SPARC CPUs have many more.  The SPARC specification allows for anywhere from 64 to upwards of 528 (on SPARC v9).  Like Berkeley RISC, SPARC implements register windowing, which allows a called function to have a unique set of registers from the calling function.  These registers are organized into four groups--eight each of global, in, out, and local registers.  The eight global registers remain visible to all functions across function calls.  The out registers in a function's window become the in registers of the next function's window.  The local registers are available only to the current function.&lt;br /&gt;&lt;br /&gt;These general purpose registers are referred to by multiple names.  Collectively they can be referred to by %r0 through %r32.  More commonly they are referred to by synonyms denoting their role within the current window: %g0-%g7, %i0-%i7, %o0-%07, and %l0-%l7.&lt;br /&gt;&lt;br /&gt;To put this together, %g0-%g7, are available across all functions.  When calling a function %o0-%07, become %i0-%i7 of the called function, and conversely, %i0-%i7 are the %o0-%07 of the calling function.  This window overlap facilitates passing of parameters to called functions.  %l0-%l7 are the local registers.&lt;br /&gt;&lt;br /&gt;That's not quite all there is to registers, however.  We mentioned %g0-%g7 as being global registers.  %g0 merits special attention.  It is hardwired to zero.  Anything loaded into %g0 will be discarded, and anything read from it will always be zero.  In addition, %o6, %o7, %i6, and %i7 also have a special purpose.  When calling a function the return address will be stored in %o7, and the stack pointer will be stored in %o6 (also called %sp).  This means that %i7 contains the return address of the caller and %i6 contains the caller's stack pointer--current function's base pointer.  We'll discuss this more when we talk about calling functions and the call stack, next.&lt;br /&gt;&lt;br /&gt;Aside from the general purpose registers, there are variety of other types of registers.  There are control registers, such as Program Counter, next Program Counter, a partial arithmetic register, and Processor Status Register.  In addition, there are a variable number of floating point registers as well as various other miscellaneous registers which are beyond the scope of this discussion.&lt;br /&gt;&lt;br /&gt;Instruction Format:&lt;br /&gt;&lt;br /&gt;SPARC instructions fall into one of several categories.  I will briefly discuss arithmetic and memory instructions here, but the reader is encouraged to consult the &lt;u&gt;SPARC v9 Architecture Manual&lt;/u&gt; for more detail.&lt;br /&gt;&lt;br /&gt;Arithmetic instructions take three arguments.  This may consist of a source register, a (13-bit) immediate operand, and a destination register.  Alternatively a second source register may be substituted for the immediate operand.&lt;br /&gt;&lt;br /&gt;For example:&lt;pre&gt;&lt;br /&gt;add %i5, %g1, %g1&lt;br /&gt;add %i5, 512, %g1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first adds the value found in input register 5 to the value found the the first global register and stores the result in the first global register.&lt;br /&gt;&lt;br /&gt;The second example addes the value found in input register 5 to the literal value 512 and stores the result in the first global register.&lt;br /&gt;&lt;br /&gt;Memory operations consist of load and store.  Memory instructions take two arguments, a source and a destination.&lt;br /&gt;&lt;br /&gt;For example:&lt;pre&gt;&lt;br /&gt;st %r5, [%r4+8]&lt;br /&gt;ld [%r4 + 8], %r6&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the above examples, the first calculates a memory address from adding 8 to the value in register 4.  The value found in register 5 is then stored in the memory at the computed memory address.&lt;br /&gt;The second exmaples performs the reverse operation.  The data located at the computed address is loaded into register 6.&lt;br /&gt;&lt;br /&gt;In addition to integer arithmetic and memory instructions, there are control flow instructions and floating point (real numbers such as pi) instructions.&lt;br /&gt;&lt;br /&gt;Function Calls &amp;amp; the Stack:&lt;br /&gt;With over 500 registers, who needs a stack?  It turns out that, like the x86 discussed previously, the SPARC utilizes a stack for keeping track of function calls.  However there are some important differences in the way the stack and function calls work between x86 and SPARC, some of which has been alluded to already in our discussion of registers.&lt;br /&gt;&lt;br /&gt;The stack on SPARC, implemented in main memory, starts at high memory addresses and grows toward lower addresses, making the "bottom" of the stack at the top and the "top" of the stack at the bottom.  When we need to allocate space on the stack we will decrement the stack pointer, so that it is pointing at a lower address in memory.  Though unintuitive, this should be familiar from our discussion of x86.&lt;br /&gt;&lt;br /&gt;Similar to x86, the stack is a place to record tops and bottoms of stack frames as the frames are created when functions are called.  Where things begin to differ is the handling of parameters that are passed to called functions.  Due to the relatively large number registers and the windowing technique inherited from Berkeley RISC, up to six parameters can simply be placed into registers rather than placed on and retrieved from the stack.  This is particularly beneficial given the speed advantages of register access vs memory access.  Given the lack of a direct address mode and the resulting requirement of multiple instructions to accomplish a single memory access, the ability to pass parameters via registers becomes doubly important.&lt;br /&gt;&lt;br /&gt;When a function is called, generally control is transferred via either the jumpl or call instructions.  call writes the value stored in PC (its own address) into %o7, to be used by the called function as the return address.  jumpl writes the return address into a register specified in the instruction.  However, the primary difference between jumpl and call is their respective addressing modes, with call being PC-relative, and jumpl being register-indirect.  A call instruction will contain an offset from the current PC value.  jumpl will specify a register and possibly an offset.&lt;br /&gt;&lt;br /&gt;Once control is transferred, the first instruction in the called function is a save instruction like the following:&lt;pre&gt;&lt;br /&gt;save    %sp, -120, %sp&lt;/pre&gt;&lt;br /&gt;One thing that the save instruction does is manipulate a special register that keeps track windows.  When executed, save decrements (yes, decreases) the Current Window Pointer, or CWP.&lt;br /&gt;&lt;br /&gt;Remember from our discussion of registers that %sp and %o6 are synonyms for the same register.  Also recall that the caller's %o6 becomes the callee's %i6.  This means that the caller's stack pointer becomes the callee's frame pointer.  In other words, the top of the caller's frame becomes the bottom of the callee's frame.  The callee's first instruction, save, creates the new frame by decrementing its own stack pointer.  How can the save instruction decrement the newly acquired %sp (%o6) if it doesn't contain a known value?  What isn't immediately obvious, but is absolutely crucial, is that in the above save instruction, the two references to %sp, are actually two *different* registers.  What is happening is that between the first %sp reference, and the second, the CWP is getting incremented, so the second %sp refers to a register in the new window.  The save instruction subtracts a value from the outgoing %sp and stores it in the incoming %sp, thus creating a new stack frame with space allocated.&lt;br /&gt;&lt;br /&gt;When we're ready to return to a calling function there are a number of cleanup steps that must be accomplished.  First, remember that the steps required to call and execute a function are played back in reverse.  This means, among other things, that the input registers, %i0-%i7, will become the output registers of the caller.  If there is return value currently stored in the local registers or our stack frame, it should be placed in an appropriate *input* register.  In order return control to the caller, we must jump back using the address the caller placed in our %i7.  This is accomplished with the synthetic ret instruction.  The ret actually accomplishes a jumpl instruction similar to&lt;pre&gt;&lt;br /&gt;jumpl %i7+8, %g0&lt;/pre&gt;&lt;br /&gt;Which causes a jump 8 bytes from the address stored in %i7, storing the return address in %g0.  Since we're returning from a called function there's no need to store the return address.  This is why %g0, which is hardwired to zero, is specified as an argument.  The return address is discarded.  After ret, increments the CWP, shifting us back to the previous window.  Since the previous %sp/%o6 are now visible, the previous stack frame is effectively destroyed.&lt;br /&gt;&lt;br /&gt;There are two more issues regarding function calls and the stack, which should be mentioned briefly for the sake of completeness.  First, what if there are more than six parameters to pass to a function?  In this case, the additional parameters must be stored on the stack.  Also, since there are a finite number of registers, there are a finite number of register windows.  This is the number of general registers, less the globals, divided by 16, to be exact.  What happens if we are so many function calls deep that we run out of windows?  In this case, the CWP reaches zero, causing a trap, which causes the next register window to be saved to the stack before being used.&lt;br /&gt;&lt;br /&gt;Okay, that was a long set up, but it was necessary establish a context for the program we're going to look at.  Again, this is the same simple program we looked at in the x86 demo.&lt;br /&gt;&lt;br /&gt;Here is the program:&lt;pre&gt;&lt;br /&gt;int a=4;&lt;br /&gt;int b=5;&lt;br /&gt;&lt;br /&gt;int adder(int d, int e)&lt;br /&gt;{&lt;br /&gt;    int c;&lt;br /&gt;    c = d + e;&lt;br /&gt;    return c;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;    int c;&lt;br /&gt;    c = adder(a, b);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;This program has a main() and a function called adder().  main() calls adder(), passing the values of two global variables as parameters.  adder() then adds the values passed into it and returns the result.  We will look at how the parameters to be passed are stored in registers and how the adder() function is called, creating the new stack frame.  Then we'll see how the result is returned, the stack frame is destroyed, and how control is transferred back to main().&lt;br /&gt;&lt;br /&gt;Again, gcc can produce the compiled, but not yet assembled program like so:&lt;pre&gt;&lt;br /&gt;gcc -S adder.c&lt;/pre&gt;&lt;br /&gt;The assembly-language output is saved in adder.s.&lt;br /&gt;&lt;br /&gt;Let's take a look:&lt;pre&gt;&lt;br /&gt;    .file "adder.c"&lt;br /&gt;    .global a                #our global variable a&lt;br /&gt;    .section ".data"&lt;br /&gt;    .align 4&lt;br /&gt;    .type a, #object&lt;br /&gt;    .size a, 4&lt;br /&gt;a:&lt;br /&gt;    .long 4&lt;br /&gt;    .global b                #our global variable b&lt;br /&gt;    .align 4&lt;br /&gt;    .type b, #object&lt;br /&gt;    .size b, 4&lt;br /&gt;b:&lt;br /&gt;    .long 5                  #the values for a and b are written directly in the assembled program&lt;br /&gt;                         #rather than being initialized at runtime.&lt;br /&gt;    .section ".text"&lt;br /&gt;    .align 4&lt;br /&gt;    .global adder&lt;br /&gt;    .type adder,             #function&lt;br /&gt;    .proc 04&lt;br /&gt;adder:&lt;br /&gt;    !#PROLOGUE# 0&lt;br /&gt;    save %sp, -120, %sp      #create a stack frame for adder()&lt;br /&gt;                         #and decrement window pointer&lt;br /&gt;    !#PROLOGUE# 1&lt;br /&gt;    st %i0, [%fp+68]&lt;br /&gt;    st %i1, [%fp+72]         #store our incoming parameters to the stack&lt;br /&gt;    ld [%fp+68], %i5         #before loading them into working registers&lt;br /&gt;    ld [%fp+72], %g1         #where we will compute the answer&lt;br /&gt;    add %i5, %g1, %g1        #add the thing in %i5 to the thing in %g1, storing&lt;br /&gt;                         #the answer in %g1&lt;br /&gt;    st %g1, [%fp-20]         #store our answer&lt;br /&gt;    ld [%fp-20], %g1         #getting ready to return, load return value into %g1&lt;br /&gt;    mov %g1, %i0             #put return value into %i0, caller's %o0&lt;br /&gt;    ret                      #jump to previously saved return address&lt;br /&gt;    restore                  #Shift the register window back to main()'s registers&lt;br /&gt;    .size adder, .-adder&lt;br /&gt;    .align 4&lt;br /&gt;    .global main&lt;br /&gt;    .type main, #function&lt;br /&gt;    .proc 04&lt;br /&gt;main:                    #***************Execution starts here.*********************&lt;br /&gt;    !#PROLOGUE# 0&lt;br /&gt;    save %sp, -120, %sp      #create a stack frame for main()&lt;br /&gt;    !#PROLOGUE# 1&lt;br /&gt;    sethi %hi(a), %g1        #a time saving shortcut for loading a 32 bit constant&lt;br /&gt;    or %g1, %lo(a), %o5      #straight to a register without memory access&lt;br /&gt;    sethi %hi(b), %g1        #more on these later&lt;br /&gt;    or %g1, %lo(b), %g1      #&lt;br /&gt;    ld [%o5], %o0            #load our 'a' into out register 0&lt;br /&gt;    ld [%g1], %o1            #load our 'b' into out register 1&lt;br /&gt;    call adder, 0            #call adder with 0 offset&lt;br /&gt;    nop                      #delay slot related to pipelining--more on this later&lt;br /&gt;    mov %o0, %g1             #put adder()'s result into %g1&lt;br /&gt;    st %g1, [%fp-20]         #save %g1 to the stack&lt;br /&gt;    mov %g1, %i0             #end of function so save return value to %i0&lt;br /&gt;    ret                      #return control to caller&lt;br /&gt;    restore&lt;/pre&gt;&lt;br /&gt;Here is a synopsis of how the adder program is executed on the SPARC cpu.&lt;br /&gt;--The program starts by executing main.&lt;br /&gt;--main()'s stack frame is created by subtracting some value from the caller's %sp, shifting the register window, and storing new stack pointer in main()'s %sp&lt;br /&gt;--A series of shortcuts is used to load a and b as 32-bit constants into registers using immediate mode, requiring only two instructions each.&lt;br /&gt;--Transfer to control to the address adder() with 0 offset.&lt;br /&gt;--A delay is required after the call instruction since other instructions are in the pipeline.  If the compiler can't find a useful instruction not related to adder(), it put's in a nop.&lt;br /&gt;--Once in adder(), we set up a new stack frame&lt;br /&gt;--Move our incoming parameters around using the stack as an intermediate storage area&lt;br /&gt;--Perform the addition, storing the result in %g1&lt;br /&gt;--Store the result from %g1 onto the stack space allocated for variable c.&lt;br /&gt;--Before returning from adder(), the return value should be loaded from c into a register&lt;br /&gt;--The return value should be moved into one of the callee's input registers which will become the caller's output register after the return.&lt;br /&gt;--Ret jumps back to previously saved return address&lt;br /&gt;--Restore increments the CWP, shifting the register window and popping the old stack frame&lt;br /&gt;--Back in main(), the return value is stored in the space on the stack allocated for c.&lt;br /&gt;--Prior to exit from main(), result from adder is relocated to a register that will be accessible by the caller.&lt;br /&gt;--Control is transferred to the caller, and the register window is shifted back once again.&lt;br /&gt;&lt;br /&gt;Some additional notes:&lt;br /&gt;Global variables a and b already have values at compile time, which allows them to be treated as constants by the assembler.  This allows the compiler to optimize the program by loading their values straight into registers without the overhead required for memory access.  However, SPARC instructions are all 32-bits wide.  By the time you subtract bits for the opcode, register reference, and other things, only 22 bits remain for an immediate value (depending on instruction format).  There is no way to place a 32-bit integer in 32-bit instruction as an immediate value.  This is where the sethi and or instructions come in.  sethi loads a 22-bit immediate value into the upper 22 bits of the lower word of the specified (64-bit) register, and clears the lower 10 bits to zero.  Then, the or instruction ORs a 10-bit immediate value with low 10 bits of the specified register.  This saves time by eliminating the multiple instructions required for a register-indirect memory access, as well as the inherent delay in accessing slower system memory vs faster cpu registers.&lt;br /&gt;&lt;br /&gt;Due to the SPARC's pipelining--the technique of having multiple instructions "in flight" at the same time, a delay slot must be incorporated between a call instruction and actual transfer of control to the called function.  This creates a bubble in the pipeline, allowing us to transfer without affecting the instructions that will come after.  The compiler will generally attempt to place an instruction in this slot which does not depend on the outcome of the called function.  If no such instruction can be found, then a nop is used, which has no effect.&lt;br /&gt;&lt;br /&gt;For more information:&lt;br /&gt;&lt;a href="http://developers.sun.com/solaris/articles/sparcv9.html"&gt;The SPARC v9 Architecture Manual&lt;/a&gt;(sun.com)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/product/0131493868/002-4585791-6016045?v=glance&amp;amp;n=283155"&gt;PANIC! UNIX System Crash Dump Analysis&lt;/a&gt;(amazon.com)&lt;br /&gt;This book, though out of print, is an excellent reference on SPARC architecture.  Even if you're not interested in crash dump analysis, just skip to part 2, "Advanced Studies."  In addition to coverage of program execution, it goes on to cover topics related to any modern operating system, including the kernel, virtual memory, file systems, and others.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://www.ngssoftware.com/papers/sparc.zip"&gt;paper&lt;/a&gt;(ZIP file!) by David Litchfield covering overflows on SPARC.  A brief introduction to execution on SPARC, before going on to exploiting buffer overflows to gain control of execution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-115642046883805214?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/115642046883805214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=115642046883805214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/115642046883805214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/115642046883805214'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/08/execution-on-sparc-cpus.html' title='Execution on SPARC CPUs'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-115626933638501844</id><published>2006-08-22T13:45:00.003-04:00</published><updated>2010-06-19T14:52:46.023-04:00</updated><title type='text'>Execution on Intel x86 CPUs</title><content type='html'>&lt;i&gt;I know I said back in May that I was going to post a couple of articles about CPU execution.  Well, I got &lt;a href="http://stephanieexperience.blogspot.com/2006/07/munich.html" target="_blank"&gt;busy&lt;/a&gt; and stuff, then three months happened, and now it's August.  Anyway, here it is.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I decided to throw together a brief demo of how x86 cpus are organized, and how they execute instructions.&lt;br /&gt;&lt;br /&gt;In terms of register organization, x86 CPUs essentially fall under the 2nd category described in the Mano[1] text--that of general register organization.  They have six general purpose integer registers, 4 of which can be accessed 8, 16, or 32 bits at a time, and a number of special purpose registers such as floating point registers, and others that are beyond the scope of this discussion.  In addition there are two registers that are essential to stack operations: the base pointer and the stack pointer.  Although x86s don't utilize a stack in the same way as the "stack organized" CPUs Mano describes, the concept of a stack is still central to x86 execution.  We can see how instructions are executed by looking at a simple program:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int a=4;&lt;br /&gt;int b=5;&lt;br /&gt;&lt;br /&gt;int adder(int d, int e){&lt;br /&gt;  int c;&lt;br /&gt;  c = d + e;&lt;br /&gt;  return c;&lt;br /&gt;}&lt;br /&gt;int main(){&lt;br /&gt;  int c;&lt;br /&gt;  c = adder(a, b);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This program has a main() and a function called adder().  main() calls adder(), passing the values of two global variables as parameters.  adder() then adds the values passed into it and returns the result.  It is worth looking at how a function is called and a value is returned, because the stack makes it possible.&lt;br /&gt;&lt;br /&gt;One very important thing to understand and keep straight regarding the x86 stack implementation is that the stack is upside down.  What I mean by this, is that as the stack grows as things are pushed on to it, it grows toward lower (smaller) addresses.  This is not intuitive.  If the base pointer and stack pointer both contain address 10, and an item is pushed onto the stack, the stack pointer will then contain address 9.  So, a reference to the "bottom" of the stack or a location "lower" on the stack refers to something at a higher address.  Something "higher" or at the "top" of the stack is at a lower address.  I just picture the stack as a stalactite growing from the ceiling of a cave.&lt;br /&gt;&lt;br /&gt;In order to see how this program is executed we can look at the assembly language produced by the compiler.  You can tell gcc to compile the program but not assemble it with the -S option:&lt;br /&gt;&lt;br /&gt;gcc -S adder.c&lt;br /&gt;&lt;br /&gt;The assembly-language output is saved in adder.s.&lt;br /&gt;&lt;br /&gt;For reasons I'll explain below, we're going to add one more option to gcc.  This will result in output that is easier to read.&lt;br /&gt;&lt;br /&gt;A simple incantation:&lt;pre&gt;&lt;br /&gt;gcc -mpreferred-stack-boundary=2 -S adder.c&lt;/pre&gt;&lt;br /&gt;Yields our compiled, but not assembled, program, adder.s, so let's take a look.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  .file    "adder.c"&lt;br /&gt;.globl a                        #our global variable, a&lt;br /&gt;  .data&lt;br /&gt;  .align 4&lt;br /&gt;  .type    a, @object&lt;br /&gt;  .size    a, 4                 #It's 4 in size because an int on a 32-bit x86 is 32 bits.&lt;br /&gt;a:&lt;br /&gt;  .long    4&lt;br /&gt;.globl b                        #our global variable, b&lt;br /&gt;  .align 4&lt;br /&gt;  .type    b, @object&lt;br /&gt;  .size    b, 4&lt;br /&gt;b:&lt;br /&gt;  .long    5                    #the values for a and b are written directly in the assembled program&lt;br /&gt;                                #rather than being initialized at runtime.&lt;br /&gt;  .text&lt;br /&gt;.globl adder&lt;br /&gt;  .type    adder, @function&lt;br /&gt;adder:                          #the adder() function&lt;br /&gt;  pushl    %ebp                 #Save the caller's base pointer on the stack&lt;br /&gt;  movl    %esp, %ebp            #make the old "top" the new "bottom"&lt;br /&gt;  subl    $4, %esp              #allocate 4 bytes on the stack for local variable c&lt;br /&gt;  movl    12(%ebp), %eax        #move the thing stored 12 bytes "below" the base pointer into register A&lt;br /&gt;  addl    8(%ebp), %eax         #add the thing stored 8 bytes "below" the base pointer to the thing in reg A&lt;br /&gt;  movl    %eax, -4(%ebp)        #store the answer in the space we allocated on the stack earlier&lt;br /&gt;&lt;br /&gt;  movl    -4(%ebp), %eax        #we're about to destroy the stack current stack frame, so better save our&lt;br /&gt;                                #return value in a register.&lt;br /&gt;&lt;br /&gt;  leave                         #this destroys the current stack frame by reversing the first two steps:&lt;br /&gt;                                #move %ebp to %esp, making the current "bottom" the new "top",&lt;br /&gt;                                #then then pop the saved base pointer back into %ebp&lt;br /&gt;&lt;br /&gt;  ret                           #the previously saved instruction pointer is popped from the stack and&lt;br /&gt;                                #execution returns to where we left off in main()&lt;br /&gt;  .size    adder, .-adder&lt;br /&gt;.globl main&lt;br /&gt;  .type    main, @function&lt;br /&gt;main:                           #***************Execution starts here.*********************&lt;br /&gt;                                #The next two steps are always used to step up a new stack frame for&lt;br /&gt;                                #The current function:&lt;br /&gt;  pushl    %ebp  #&lt;-------------%ebp is a register containing the address of the "bottom" of the stack&lt;br /&gt;                                #we're going to save it by pushing it onto the stack   &lt;br /&gt;  movl    %esp, %ebp  #&lt;---------make the current stack pointer the new "bottom"    &lt;br /&gt;  subl    $4, %esp              #Allocate some space on the stack, specifically 4 bytes, for local variable c&lt;br /&gt;                                #by subtracting 4 from the stack pointer.  On x86 the stack grows upside down,&lt;br /&gt;                                #so it starts at higher addresses and grows toward lower ones.    &lt;br /&gt;  movl    b, %eax               #Move our global variable, a, into the A register   &lt;br /&gt;  movl    a, %edx               #Move b into the D register    &lt;br /&gt;  pushl    %eax                 #Preparing for the function call to adder() we need to push   &lt;br /&gt;  pushl    %edx                 #the parameters we'll be passing onto the stack&lt;br /&gt;&lt;br /&gt;  call    adder()               #the instruction pointer is pushed onto the stack and execution jumps to adder   &lt;br /&gt;  addl    $8, %esp              #clean up the the stack   &lt;br /&gt;  movl    %eax, -4(%ebp)        #save the return value, previously saved in the A register, on the stack for later use   &lt;br /&gt;  leave                         #we're done with main, so destroy the stack frame   &lt;br /&gt;  ret &lt;/pre&gt;&lt;br /&gt;So here is a synopsis of how this simple program gets executed on an x86 CPU:&lt;br /&gt;--The program starts by executing main.&lt;br /&gt;--A stack frame for main() is set up by saving the contents of the base pointer register to the stack, then moving the contents of the stack pointer to the base pointer.&lt;br /&gt;--Four bytes are allocated on the stack, for the local variable, c.&lt;br /&gt;--The values that will be passed to adder() are located in global variables, which are located in memory somewhere other than the stack.  In order for the values to be used by adder(), they must located on the stack.  They must first be moved to registers before they can be pushed onto the stack.&lt;br /&gt;--From there they are pushed onto the stack for use by the soon to be called adder() function.&lt;br /&gt;--When the adder() function is called, the current instruction pointer is saved to the stack (implicitly by the call instruction) and execution jumps to adder.&lt;br /&gt;--Once in adder, the steps to set up a new stack frame are repeated.&lt;br /&gt;--Space is allocated on the stack for adder()'s local variable, also called c.&lt;br /&gt;--Adder then grabs the numbers to be added from "below" its stack frame and performs the addition, saving the result to the the space allocated on the stack for local variable c.&lt;br /&gt;--Before returning to main, which will destroy the current stack frame, the contents of the local variable, c, are moved from the stack into the A register for use by main.&lt;br /&gt;--Adder's stack frame is then destroyed and execution returns to the point where it left off in main.&lt;br /&gt;--Adder's return value, previously stored in the A register is saved to the stack for further use.&lt;br /&gt;--With nothing left to do, the leave instruction destroys main()'s stack frame and the ret instruction returns control of execution to the calling program.&lt;br /&gt;&lt;br /&gt;Some additional notes:&lt;br /&gt;This assembly code uses AT&amp;amp;T syntax.  Among other things, it is characterized by specifying a source register or address, followed by destination.  Alternatively, there also is Intel syntax, which does a number of things differently.  However, the finer points of the syntax are really dependent on the assembler being used and aren't really tied to the hardware.&lt;br /&gt;&lt;br /&gt;It also is worth noting that there are a number of operations that may seem unnecessary or less than optimal.  This is attributable to several things.  First, this is an artificially simple program.  It adds two numbers together and then quits.  The adder() function moves the result from the A register to the location on the stack allocated for c.  We told it to do this when we said 'c='.  It then moves the contents of c into the A register because it has to.  adder()'s stack frame is about to be destroyed along with any local variables it may have.  Also, there are a number of different ways that a high level program can be implemented in low level instructions and still accomplish the same effect.  The assembly code generated is very compiler-dependent.&lt;br /&gt;&lt;br /&gt;Lastly, recent versions of gcc, when compiling for x86, like to align the stack on a 16 byte boundary.  This results in lots of extraneous stack allocations and housekeeping.  Though this is almost certainly some sort of optimization for modern CPUs and is done for a very good reason, it makes for very difficult-to-read assembly code.  For this reason, we used the -mpreferred-stack-boundary=2 option to align the stack to a 2^2 byte boundary.  This made the stack 4 bytes wide rather than 16.&lt;br /&gt;&lt;br /&gt;[1] This demo was originally written in the context of an undergraduate Computer Architecture class and is intended to be tied to relevant discussions from the computer architecture text by Morris Mano.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-115626933638501844?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/115626933638501844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=115626933638501844' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/115626933638501844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/115626933638501844'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/08/execution-on-intel-x86-cpus.html' title='Execution on Intel x86 CPUs'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-114748786329772922</id><published>2006-05-12T22:36:00.001-04:00</published><updated>2008-08-29T11:20:39.931-04:00</updated><title type='text'>Computer Processor Architecture</title><content type='html'>I'd like to take the opportunity to indulge myself.  I have a couple of articles that I have written for another purpose that I'd like to post as a two-part series.  They're fairly technical, and, as such, may not be of general interest to most people.  However, if you've ever been curious about how a computer's processor, or CPU, works, then they may be worth taking a look at.&lt;br /&gt;&lt;br /&gt;In the articles, we'll take a look at a simple C program and analyze how that program gets executed on two different types of CPUs.  There are a few things that these articles leave to the reader to understand.  Among them are a general familiarity with C-style programming syntax.  Also assumed is a basic understanding of CPU organization, especially the notion of registers.  An essential concept to both articles is that of a stack, as it relates to data being organized in a computer's memory.  Lets take a moment to discuss these ideas.&lt;br /&gt;&lt;br /&gt;A CPU must have registers, which are very small but fast memory locations built right into the cpu.  They are designed to hold operands which are used in the CPU's operations.  For example, if a processor with two regisers were instructed to add 1+2, it might store 1 in one register, and 2 in the other.  Then having quick access to the operands, it can add them and store the result in one of the two registers.  Registers can be used in other ways, too, such as storing the memory address where a paricular operand is to be found.&lt;br /&gt;&lt;br /&gt;A stack, as it relates to computer memory, simply is an organizational structure for data.  It is exactly like the spring-loaded plate warmer at a buffet.  After taking a plate of the stack, the stack rises to present the next plate.  A plate can be added to the stack, causing the stack to be pushed down, accomodating the new plate.  A stack data structure works the same way.  A stack can be accessed with a "push," "pop," or "peek" operation.  A data item can be pushed onto the stack, or popped off of it.  Some stacks may also allow a peek at the next item without removing it.  Less strict stack implementations allow accesses at arbitrary locations within the stack.  For obvious reasons, a stack is sometimes characterized as being a last in first out, or LIFO, data structure.&lt;br /&gt;&lt;br /&gt;Briefly, I'll introduce the program we'll look at in the CPU articles.  This is a simple program that adds two numbers.  The program follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int a=4;&lt;br /&gt;int b=5;&lt;br /&gt;&lt;br /&gt;int adder(int d, int e){&lt;br /&gt;  int c;&lt;br /&gt;  c = d + e;&lt;br /&gt;  return c;&lt;br /&gt;}&lt;br /&gt;int main(){&lt;br /&gt;  int c;&lt;br /&gt;  c = adder(a, b);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This program has two integer variables, &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, which are set equal to 4 and 5 respectively.  The program starts running at the &lt;code&gt;main()&lt;/code&gt; function.  Main has an integer variable, &lt;code&gt;c&lt;/code&gt;, which will be used to hold the result from the addition.  From within &lt;code&gt;main()&lt;/code&gt;, another function, &lt;code&gt;adder()&lt;/code&gt;, is called to perform the addition.  The &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; variables are sent to &lt;code&gt;adder()&lt;/code&gt; for addition.  &lt;code&gt;adder()&lt;/code&gt; receives the contents of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; storing them in its own variables, &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;e&lt;/code&gt;, respectively.  It also has its own integer variable, &lt;code&gt;c&lt;/code&gt;.  &lt;code&gt;d&lt;/code&gt; and &lt;code&gt;e&lt;/code&gt; are added and stored in &lt;code&gt;c&lt;/code&gt;.  Then the value stored in &lt;code&gt;c&lt;/code&gt;, is returned to &lt;code&gt;main()&lt;/code&gt;, from whence &lt;code&gt;adder()&lt;/code&gt; was called.&lt;br /&gt;&lt;br /&gt;There, in about 3000 characters, is a very brief introduction to a few concepts that will be central to the next couple of posts.  Like I mentioned, these are somewhat of an indulgence for me.  Though they may not be of general interest, this is a topic that I find very interesting, so hopefully somebody else will, too.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-114748786329772922?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/114748786329772922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=114748786329772922' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114748786329772922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114748786329772922'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/05/computer-processor-architecture.html' title='Computer Processor Architecture'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-114721652841652605</id><published>2006-05-09T19:04:00.000-04:00</published><updated>2006-11-12T18:22:28.814-05:00</updated><title type='text'>Keyboard Tray Lighting</title><content type='html'>The desk that I use at home has a lap drawer that pulls out to be a keyboard tray.  It works pretty well and is a nice desk, but one thing that has always bugged me is that when I pull out the keyboard the desktop casts a shadow over the top few rows of keys.  I'm always having to bend my neck down to get a good look at the keys to make sure I've got my hands lined up in the right place.  I always thought it would be great if I could mount some sort of small light under the desktop that would illuminate the keyboard.  I know there are really bright LEDs available in various colors. including white, but I didn't want to buy loose LEDs and try to inegrate them into a lighting system.  I didn't want to have to deal with attaching them to something, converting voltage, etc.  Then I remembered cold cathode tubes, which are readily available for people who trick out their computer cases (I've used them &lt;a href="http://www.flickr.com/photos/zach_steph/140566660/in/photostream/"&gt;before&lt;/a&gt;).  I checked on directron.com and found a kit that included two 12" white tubes which would be perfect.  Since they are for use inside a PC they use 12 volts DC which I could easily supply using a 12V AC/DC wall adapter.&lt;br /&gt;&lt;br /&gt;After ordering and receiving the lights, I headed to Radio Shack to pick up a few parts (it wasn't quite that easy--there was quite a bit of thinking involved in the mean time).  I would need a power supply, some sort of spring loaded switch (like a button or lever), and a way to connect the power supply to the lights.&lt;br /&gt;&lt;br /&gt;Radio Shack carries a variety DC power adapters in varying voltages, that all have a modular connector on the end to accomodate a variety of available power tips, available separately, one of which hopefully will match your electronic device.  You get to pick one power tip for free with the purchase of an adapter.  In the electronic compenents section of the store, among other things, there are DC power jacks ready for soldering that are available in surface mount (for mounting in a box or enclosure) or inline (for hanging off the end of a cable) form factors.  They are coded with different letters so you can get matched plug and jack.  It turns out that the same letter codes are also labeled on the power tips that go with the DC adapters.  This makes finding and choosing an appropriate DC adapter and power tip to match your project very easy.  I went with the "M" size.  No particular reason--it just looked like a good size.  The smallest power adapter they had in 12V DC was 500ma, which is unfortunate because my lighting kit only draws a meager 5ma.&lt;br /&gt;&lt;br /&gt;For a switch, I chose a lever switch.  My thinking was that as I slid the keyboard drawer in, the lever would get pushed downward by some object which I would attach to the underside of the desktop, like a wedge of wood or some such.  I considered using a push button type switch, which I could attach to the backside of the drawer and would be pushed in when the drawer was fully closed.  However I was worried that the spring in the switch would be stiff enough that it would cause the drawer to spring back out, leaving the switch in its "on" position.&lt;br /&gt;&lt;br /&gt;Here are the parts and part numbers that I used:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Mini SPDT Lever switch: 275-0016&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Inline power jack: 274-1577&lt;/li&gt;&lt;br /&gt;&lt;li&gt;AC/DC Adapter: 273-1773&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Power tip for AC/DC adapter: 273-1716&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Cold cathode &lt;a href="http://directron.com/clk12wt.html"&gt;lighting kit&lt;/a&gt; from directron.com&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Here are some pictures showing what I did, along with some descriptions.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140517020/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/54/140517020_29d0da0d7e.jpg" width="500" height="375" alt="keyboard_light_switch_doohickey.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;In this picture, you see the mechanism responsible for tripping the lever switch when the keyboard drawer would be closed.  I spent the most time figuring this part out.  I was thinking of using a wood block or wedge or something.  The problem is the amount that the object would have to hang down must be very precise.  It couldn't hang down low enough to obstruct the free movement of the keyboard drawer.  On the other hand it must hang down enough to cause the lever switch to be pressed down completely, opening the circuit.  Based on my measurements, that only gave me a margin of about 1/8" to play with.  Then I realized that by using a strip of metal I could flex and bend it until I had the clearance just right.  I decided to use one of those metal blanks that covers the unused expansion slots on the back of a PC.  Using fairly small screws, I attached it to the underside of the desk.  I had measured and made marks earlier, so I knew right where it needed to go.  A pair of channel-locks where ideal for bending the metal into an appropriate shape.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140516880/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/46/140516880_8f1813ebaf.jpg" width="500" height="375" alt="keyboard_light_wiring.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;In this picture you see the wiring harness with my inline power jack soldered onto it, as well as the lever switch.  The lighting kit came all wired together with a switch and power connector ideal for use inside a PC.  I chopped those off and soldered on my own.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140516957/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/44/140516957_951093b95a.jpg" width="500" height="375" alt="keyboard_light_switch.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;Here, you see the miniature lever switch tacked onto the rear end of the side of the keyboard drawer.  The switch is oriented so that the lever will be pushed down as the drawer is slid in.  You may also notice my extra crispy heat-shrink tubing.  I was lazy and didn't feel like getting out the heat gun, so I used a lighter instead.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140517084/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/52/140517084_9b58fe87f7.jpg" width="500" height="375" alt="Keyboard_lights.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;In this picture, you see the actual lights attached to the underside of the desktop along with the power inverter.  The lights operate on 300V DC, and the power inverter converts the 12V DC to to voltage appropriate for the lights.  The power wire is easily attached and dettached from the power inverter.  This is so that the keybard tray can be completely removed if necessary.  The power inverter is attached with velcro and can be repositioned if necessary.  I'm not really satisfied with how I attached the lights.  I used a staple gun to attach zip ties in the spots where I wanted the lights to be attached.  Then I cinched the zip ties down on the lights.  Zip ties are kind of ghetto, but I didn't want an extremely permanent solution like epoxy or anything like that.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140594324/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/45/140594324_bb60c5e93a.jpg" width="500" height="375" alt="desk_lighting_power_strip.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;Here is the power strip tucked away inside the cabinet of my desk that controls all of my lights.  All the lights on and around my desk are plugged into this power strip, such that the switch controls them all.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140516758/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/45/140516758_879a052993.jpg" width="500" height="375" alt="keyboard_tray_light_off.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;In this picture the keyboard drawer is pushed all the way in and the light is off.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/zach_steph/140516818/" title="Photo Sharing"&gt;&lt;img src="http://static.flickr.com/55/140516818_d79b4955d8.jpg" width="500" height="375" alt="keyboard_tray_light_on.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;In this picture the keyboard drawer is pulled out, and you can see the glow of the white lights on the keyboard and trackball.&lt;br /&gt;&lt;br /&gt;Not counting preliminary head scratching and trips to Radio Shack, the project took about two hours.  I'm really pleased with how it turned out--it solves the problem perfectly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-114721652841652605?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/114721652841652605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=114721652841652605' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114721652841652605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114721652841652605'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/05/keyboard-tray-lighting.html' title='Keyboard Tray Lighting'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-114634787492822379</id><published>2006-04-29T17:35:00.000-04:00</published><updated>2006-11-12T18:22:28.729-05:00</updated><title type='text'>Middle Finger</title><content type='html'>I seldom write new posts, because I seldom have things I want to write about.  My wife says I should write about things like this, so here you go.&lt;br /&gt;&lt;br /&gt;Friday, when I was driving home from work, I was merging onto a very busy Highway 32 from I-95.  Highway 32 is a six lane highway--three each way.  Just as I was getting into the merge window, a guy in the center lane changed into the right lane right where I needed to get.  I was already going faster than him, so there was just enough room to slice in right before my merge lane ran out.  It was close, but since I was already going faster that he was, he didn't have to slow down.  It definitely was &lt;i&gt;not&lt;/i&gt; a cutoff.  Evidently he though it was because right after I sliced in, he proceeded to flash his (I assume) bright lights at me.  &lt;br /&gt;&lt;br /&gt;The distance between us continued to grow, and within a few seconds I was able to make my way over to my rightful place--the far left lane.  The other guy must have realized that bright lights are ineffective as an offensive tool at 3:00 pm on a sunny afternoon. I noticed in my peripheral vision that he had switched back to the center lane, caught up with me, and matched my speed.  We were now neck-and-neck.  I was certain he had arrived to deliver yet further vengeance upon me.&lt;br /&gt;&lt;br /&gt;Not wanting to give him the satisfaction, I continued to look ahead rather than at him.  He could not communicate his hateful message if I refused to receive it.  Eventually, however, I surrendered to my curiosity.  Looking to the right, sure enough, I was greeted by a middle finger.  Attached to the middle finger was a very angry man.  The man was mouthing something at me, but with two panes of automotive glass, four feet, and 74 miles per hour worth of rushing wind between us, I was unable to make out his message.  I am about 90% certain it involved the word "fuck."&lt;br /&gt;&lt;br /&gt;The thing is, I wasn't angered by this childish display of insolence.  It made me envious.  What simple problems he must have. If the worst thing that I had to worry about all day long was some guy cutting in front of me in traffic, life would truly be good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-114634787492822379?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/114634787492822379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=114634787492822379' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114634787492822379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114634787492822379'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/04/middle-finger.html' title='Middle Finger'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-114100040969159113</id><published>2006-02-26T19:23:00.000-05:00</published><updated>2006-11-12T18:22:28.414-05:00</updated><title type='text'>The Google Calculator</title><content type='html'>If you have never used google's built in calculator, now's a good time to take a look at it.  It's quite handy.&lt;br /&gt;&lt;br /&gt;Here's a quick introduction.&lt;br /&gt;&lt;br /&gt;You can simply type your mathematical expression into Google's search bar to get the answer.&lt;br /&gt;&lt;br /&gt;For example, you can obvious things like&lt;br /&gt;&lt;pre&gt;(3*768)/(456.7+28)&lt;/pre&gt; to obtain the following result&lt;br /&gt;&lt;pre&gt;(3 * 768) / (456.7 + 28) = 4.75345575&lt;/pre&gt; with 8 decimal places of precision.&lt;br /&gt;&lt;br /&gt;You can also do less obvious things like perform unit conversion:&lt;br /&gt;For example, &lt;pre&gt;7 miles to kilometers&lt;/pre&gt; gives:&lt;br /&gt;&lt;pre&gt;7 miles = 11.265408 kilometers&lt;/pre&gt; and&lt;br /&gt;&lt;pre&gt;3 gallons to cups&lt;/pre&gt; yields:&lt;br /&gt;&lt;pre&gt;3 US gallons = 48 US cups&lt;/pre&gt; (I think google returns localized results based on your ip address, so the result to conversion queries may vary)&lt;br /&gt;&lt;br /&gt;But the fun doesn't stop there.&lt;br /&gt;Entering the phrase "8670 to binary" yields:&lt;br /&gt;&lt;pre&gt;8 670 = 0b10000111011110&lt;/pre&gt; and,&lt;br /&gt;&lt;pre&gt;0b10000111011110 to octal:&lt;/pre&gt;gives&lt;pre&gt;0b10000111011110 = 0o20736&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;0o20736 to hex:&lt;/pre&gt;gives&lt;pre&gt;0o20736 = 0x21DE&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;0x21DE to decimal:&lt;/pre&gt;gives&lt;pre&gt;0x21DE = 8 670&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Base conversion appears to work only for integers, sadly.  How cool would floating point decimal to binary conversion be?  Very.&lt;br /&gt;&lt;br /&gt;Anyway, give it a try--it's really handy. And if you use a web browser that has a google search box built in, like firefox, then you don't even have to go to Google's site, saving a few keystrokes.&lt;br /&gt;&lt;br /&gt;For lots more info, see the Google Calculator &lt;a href="http://www.google.com/help/calculator.html"&gt;help&lt;/a&gt; page.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-114100040969159113?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/114100040969159113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=114100040969159113' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114100040969159113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/114100040969159113'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2006/02/google-calculator_26.html' title='The Google Calculator'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-111539167033054375</id><published>2005-05-06T10:58:00.000-04:00</published><updated>2006-11-12T18:22:27.936-05:00</updated><title type='text'>Anonymous Comments</title><content type='html'>&lt;span style="font-family: trebuchet ms;"&gt;So I recently discovered a setting in my blogger.com profile that determines who can post comments. Previously, it had been set to members only, which I think is dumb. I have now changed it to "anyone." Anonymous comments should now be possible.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-111539167033054375?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/111539167033054375/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=111539167033054375' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/111539167033054375'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/111539167033054375'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2005/05/anonymous-comments.html' title='Anonymous Comments'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-111538484878749305</id><published>2005-05-06T08:23:00.000-04:00</published><updated>2006-11-12T18:22:27.863-05:00</updated><title type='text'>Portable hard drive</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;I had an old laptop hard drive laying around that I bought off of someone for cheap. It really wasn't serving any purpose and was just going to waste. Back when I had my &lt;a href="http://www.anandtech.com/mobile/showdoc.html?i=1733"&gt;Dell Inspiron 8200&lt;/a&gt;  I got an extra hard drive tray on &lt;a href="http://search.ebay.com/dell-inspiron-8200-hard-drive-caddy_W0QQfkrZ1QQfromZR8"&gt;Ebay&lt;/a&gt; and it was handy to swap the spare drive in and out to run other OSes and such. However since I got my current notebook, the 10gb hard drive has just been sitting on the shelf. Enter the USB 2.0 &lt;a href="http://www2.newegg.com/Product/Product.asp?Item=N82E16817145124"&gt;enclosure&lt;/a&gt;. I got this thing form Newegg.com for about $20 shipped. It came in yesterday. This thing is amazing. For one thing it took all of five minutes to slide the hard drive in and screw in two eye-glasses sized screws. It was so easy your mom could do it. Second, it's really small. The picture doesn't do it justice. It fits in my back pocket. If you've never seen a 2.5" notebook hard drive, then let me tell you they're amazingly small. This external enclosure adds very little to the hard drive's dimensions. Third, I just plugged it in and it worked automatically. My laptop is dual boot. Both in my preferred &lt;a href="http://ubuntulinux.org/"&gt;distrubution &lt;/a&gt;of Linux as well as Windows XP, the drive was automagically recognized. As a matter of fact, I had forgotten that I had Debian Linux installed on that hard drive previously, so when I plugged the drive in and the partitions were recognized, there was all the data and OS files that had been there previously. For the record, if you want to be able to read (and write) the maximum number of different file systems, whether it's Windows, Mac, or Linux, or others, Linux is the way to go. The Linux kernel has support for more than about a dozen or so different filesystems.&lt;br /&gt;&lt;br /&gt;The other cool thing is how the drive is powered. Since it's USB, and notebook harddrives are so low-powered, it's designed to take power off the USB port it's pluged into. This worked great for me, and my understanding is that most USB ports on notebooks and computers are cable of providing adequate power. However, in the case that your notebook's USB ports are under powered, there is a second, sort of "vampire" USB plug on the cable that you can plug to into a second port to supplement the power requirements. I didn't have to use the second plug.&lt;br /&gt;&lt;br /&gt;Anyway, this thing is really cool, and for $20 I can now put this hard drive to good use backing up my personal files or shuttling large files from one computer to another. Did I mention it's really small?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-111538484878749305?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/111538484878749305/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=111538484878749305' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/111538484878749305'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/111538484878749305'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2005/05/portable-hard-drive.html' title='Portable hard drive'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-110799578679538411</id><published>2005-02-09T19:25:00.000-05:00</published><updated>2006-11-12T18:22:27.711-05:00</updated><title type='text'>Why Digital Rights are an Illusion of Freedom</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;Recently, in a class I am taking (of the web-based distance learning variety) there was a sidebar discussion regarding the Apple iPod. The people who have the iPod were going on and on about how great it is, how it's easy to use and how you can buy songs at the iTunes Music Store.&lt;br /&gt;&lt;br /&gt;I don't have an iPod, and although I think they're a brilliant example of industrial design, with their clean lines and intuitive interfaces, there are a number of issues I would need to understand better before deciding to purchase one for myself. Most of these issues revolve around a technology called Digital Rights Management, or DRM.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Brief Description of DRM&lt;/span&gt;&lt;br /&gt;DRM is technology that enables copyright owners, namely the big four record companies, to ensure that songs you purchase online at stores like the Itunes Music Store don't end up online being swapped in file trading networks. This sounds resonable, right? After all artists (i.e., record labels) should be compensated for their work.&lt;br /&gt;&lt;br /&gt;Before we decide, however, let's take a quick look at how DRM works. There are a variety of DRM schemes, each working differently, and each have more or less restriction. However, here's a generic description of how it works. A song that you buy from an online music store is downloaded to your computer in an encrypted format. This means that you can't unlock it unless you have the right key. Of course the key has to be provided by the store where you bought the song. Naturally the key is tied specifically to that particular song, so it won't work with any other song. It doesn't stop there, though. You could simply upload a copy of the key along with a copy of the song into the ether, then everybody would be able download it, unlock it and play it, right? Right. And that just wouldn't do. So the key also is tied to your computer or music player as well, so it won't work on another computer or music player.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Historic Problems with DRM&lt;/span&gt;&lt;br /&gt;Historically, there have been a few issues with DRM that have prevented its acceptance among consumers. A major problem has been with compatibility. Music purchased from an online music store would require a special program to play it back. Music players from different online stores wouldn't be compatible. Music purchased online would almost certainly not play on a portable digital music player. Lately, Microsoft is hard at work to solve the compatibility issue. They've started the "Plays for Sure" logoing program where music players and online vendors that display the "Plays for Sure" logo are supposed to be compatible with one another. At the heart of this program is Microsoft's own Windows Media Player 10. You wouldn't accuse Microsoft of committing an act of altruism, would you? Me either. It doesn't even bare mentioning that music purchased from the "Plays for Sure" logo partners won't play back on competing operating systems like Mac OS or on Linux.&lt;br /&gt;&lt;br /&gt;Another issue was pricing. It took some time to arrive at a pricing model that was attactive to consumers. One model is a subscription that allows a certain number of downloads per month. Another is a subscription that allows all-you-can eat listening online, but no downloading. Yet another, as is the case with the iTunes Music Store, is a per song and per album pricing structure. In this scenario the customer pays a certain amount for each song downloaded, or, alternatively, a certain amount for an entire album. If the entire album is desired, the price is usually more economical than for each individual song.&lt;br /&gt;&lt;br /&gt;The big problem, however, that has prevented wider acceptance of DRM restricted online music, is with the restrictions themselves. Nobody wants to pay good money for music that can only be listened to online and not downloaded, or for music that must be kept in a virtual lockbox and can't be copied to other computers or devices. It is here, that Apple has been able to make serious inroads with their iTunes Music Store. Of all the competitors in the fledgling pay-for-download music industry, the restrictions placed on Apple's iTunes music are perhaps the least restrictive of all. Recently they've been relaxed even further to allow playback on up to five separate computers. This is in addition to the ability to burn CDs and copy to an Apple iPod (but no other type of music player of course).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Digitally Restricted Freedoms&lt;/span&gt;&lt;br /&gt;Herein lies the rub, as well as the purpose of this article: When you buy DRM-restricted music (or anything else for that matter) you are surrendering certain freedoms that we historically have taken for granted. I think folks are being duped. As DRM schemes become more broadly compatible, easy to use, more flexible in terms of restrictions, the easier it becomes to give up those freedoms.&lt;br /&gt;&lt;br /&gt;To put this into perspective, lets consider the purchase of a physical audio CD as the basis of comparison. Under the fair-use provisions of our (U.S.) copyright laws, it is acceptable to do a number of things with a music CD you have purchased. You can make copies of it. You can even make multiple copies of it, for example, one for upstairs, one for downstairs, one for the car, and even a copy to listen to at work. Maybe you even want to put the original away for safe keeping. You can also extract the songs from the CD into mp3 format for playback on your mp3 player and any and all of your computers. That, too, is legal and perfectly acceptable (note that at this point legal purists will point out that can be no case presidence for fair-use--each instance must be tested by the court). With DRM-restricted music, you usually are afforded only some subset of this flexibility. As I mentioned before, Apple has afforded a great deal of flexibility with their for-purchase music, giving the illusion of freedom.&lt;br /&gt;&lt;br /&gt;I want to make sure that last point isn't lost. Illusion. Regardless how unrestrictive a vendor's DRM is, any "freedom" it affords is only an illusion. It is for that reason that customers of iTunes are being duped. In general, people tend to think that as long as the DRM doesn't "get in my way," then it's as good as being unrestricted. That still doesn't change the fact that their perception of freedom isn't real.&lt;br /&gt;&lt;br /&gt;Put it this way--If I were to put you in prison, you most certainly would be upset with restrictions on your freedom. Even if I said you were free to move about as you wish within the confines of the prison, the fact would remain that you are in prison and cannot leave. Now, what if I expanded the walls of the prison so that you would have greater freedom of movement? I could even expand the walls so far that you could not see them. Would you not still be in prison, unable to leave? You could move about in any direction as far as you could see. For all intents and purposes you would be free, save for the fact that you couldn't leave. Regardless how unrestrictive your confines may be, your perception of freedom would be an illusion.&lt;br /&gt;&lt;br /&gt;Some may argue that the difference between my analogy and reality is that with the music, participation is optional, and in the analogy participation is compelled. Certainly the prison metaphor isn't intended to be extended to the smallest detail. However the comparison is still valid. It boils down to this. With DRM-restricted music, whenever you play back the songs you have purchased, you must ask permission, either directly or indirectly. Remember the files are encrypted not by you but by the vendor. You cannot decrypt the files for playback without a key issued by the vendor. Each time you play the file, the playback software must verify that the key is valid, has not been tampered with, and has not expired. And of course the key can be revoked at any time. So even if you can play the files when or where you want, in principle you still must ask permission each time you do. That is not true freedom--it is only the illusion of freedom at best.&lt;br /&gt;&lt;br /&gt;As a final thought, the open source sofware community likes to highlight the differences in the way we use the word free. They say there is "free as in beer" and "free as in speech." I'm not saying music should be free as in beer--artists (i.e., record companies) should be compensated. But they should be free as in liberty. Once I purchase a song or CD or book or pair of jeans, I think I should be able to use it how &amp;amp; where I want without asking anyone's permission, so long as those uses are legal. Don't you?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-110799578679538411?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/110799578679538411/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=110799578679538411' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/110799578679538411'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/110799578679538411'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2005/02/why-digital-rights-are-illusion-of.html' title='Why Digital Rights are an Illusion of Freedom'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9636763.post-110316863100638629</id><published>2004-12-15T22:20:00.000-05:00</published><updated>2006-11-12T18:22:27.325-05:00</updated><title type='text'>The Shadow File</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;This is the first post to The Shadow File. I suppose a brief explanation is in order. What is The Shadow File? In Unix and Linux, an algorithm is used to create a one-way hash of a user's password. This hash, along with the username and other information used to be stored in /etc/passwd. In many modern *nix systems, the password hash has been removed from the passwd file and is now stored in a separate file, because the passwd file is world-readable. This way, an attacker would have to obtain both files in order to attempt to recreate the password.  The file that contains the password hashes is /etc/shadow. Now you know.&lt;br /&gt;&lt;br /&gt;The things that will fill this page include my humble observations and musings on whatever projects I may be working on or anything at all that may stimulate my thoughts. So prepare to have your attention captured. I'm sure you won't be able to pry your eyes away.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9636763-110316863100638629?l=shadow-file.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shadow-file.blogspot.com/feeds/110316863100638629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9636763&amp;postID=110316863100638629' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/110316863100638629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9636763/posts/default/110316863100638629'/><link rel='alternate' type='text/html' href='http://shadow-file.blogspot.com/2004/12/shadow-file.html' title='The Shadow File'/><author><name>Zach Cutlip</name><uri>http://www.blogger.com/profile/04234441021013504307</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
