<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tyler Oderkirk&#039;s Blog &#187; Shell programming</title>
	<atom:link href="http://unsyncopated.com/blog/index.php/category/shell-programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://unsyncopated.com/blog</link>
	<description>&#34;Scared money don&#039;t[sic] make money&#34;</description>
	<lastBuildDate>Thu, 27 Jan 2011 05:02:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Storing file metadata with fnmeta.py</title>
		<link>http://unsyncopated.com/blog/index.php/2010/03/27/storing-file-metadata-with-fnmeta-py/</link>
		<comments>http://unsyncopated.com/blog/index.php/2010/03/27/storing-file-metadata-with-fnmeta-py/#comments</comments>
		<pubDate>Sat, 27 Mar 2010 16:37:04 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=784</guid>
		<description><![CDATA[The problem Have you ever named a file something like&#8230; main.cpp.GOOD &#8230; to indicate a &#8220;known-good&#8221; copy of `main.cpp`? This simplistic method for storing file metadata is great because it&#8217;s filesystem-agnostic &#8211; the metadata (e.g. &#8220;this is known-good source code&#8221;) &#8220;follows&#8221; the file wherever it goes &#8211; from ext3 to FAT32 to NTFS, etc. However, [...]]]></description>
			<content:encoded><![CDATA[<span id="The_problem"><h3>The problem</h3></span>
<p>Have you ever named a file something like&#8230;</p>
<blockquote>
<pre>main.cpp.GOOD</pre>
</blockquote>
<p>&#8230; to indicate a &#8220;known-good&#8221; copy of `main.cpp`?</p>
<p>This simplistic method for storing <em>file metadata</em> is great because it&#8217;s <em>filesystem-agnostic</em> &#8211; the metadata (e.g. &#8220;this is known-good source code&#8221;) &#8220;follows&#8221; the file wherever it goes &#8211; from ext3 to FAT32 to NTFS, etc.</p>
<p>However, it has a few limitations:</p>
<ol>
<li>Certain characters like &#8220;/&#8221;, &#8221; &#8220;, and &#8220;?&#8221;, while <em>possible</em>, become a hassle later when you need to manipulate the file by name at a shell.</li>
<li>Adding, editing, and removing metadata at a shell involves lots of line-editing acrobatics especially if you want to maintain the file&#8217;s orginal extension e.g. `main.WORKING.cpp`.</li>
</ol>
<span id="The_solution"><h3>The solution</h3></span>
<p>To work around these limitations I wrote a small utility called `fnmeta.py` (for &#8220;<strong>f</strong>ile<strong>n</strong>ame <strong>meta</strong>data&#8221;). It uses <a href="http://en.wikipedia.org/wiki/Base64">Base64 encoding</a> to store metadata, thus allowing you store arbitrary binary data. Beware <a href="http://en.wikipedia.org/w/index.php?title=Comparison_of_file_systems&amp;oldid=351665073#Limits">the limits on filename length</a> imposed by the filesystem. For the filesystems I use, the lowest common denominator is 255 characters.</p>
<p>If you ask `fnmeta.py` to store the string &#8220;foo&#8221; as metadata for the file `bar.baz`, it will rename `bar.baz` to `bar.<strong>TAG</strong>.<strong>ENCODED_METADATA</strong>.<strong>TAG</strong>.baz` where&#8230;</p>
<ul>
<li>&#8220;<strong>TAG</strong>&#8221; is the word &#8220;fnmeta&#8221; followed by a number indicating which version of fnmeta was used to encode the metadata. &#8220;fnmeta&#8221; gives a hint at why there&#8217;s a big chunk of non-english text in the filename and the number facilitates future updates to the encoding scheme.</li>
<li>&#8220;<strong>ENCODED_METADATA</strong>&#8221; is base64_encode(&#8220;foo&#8221;)</li>
</ul>
<span id="An_example"><h3>An example</h3></span>
<p>Here&#8217;s an example showing how I used `fnmeta.py` to store the URL from which I downloaded a PDF named `xapp374.pdf`:</p>
<pre class="brush: plain;">

$ fnmeta.py xapp374.pdf
please enter the new metadata: www.xilinx.com/support/documentation/application_notes/xapp374.pdf

$ ls xapp374*
xapp374.fnmeta1.d3d3LnhpbGlueC5jb20vc3VwcG9ydC9kb2N1bWVudGF0aW9uL2FwcGxpY2F0aW9uX25vdGVzL3hhcHAzNzQucGRm.fnmeta1.pdf

$
</pre>
<p>Later on, I retrieved the metadata like this:</p>
<pre class="brush: plain;">

$ fnmeta.py xapp374.fnmeta1.d3d3LnhpbGlueC5jb20vc3VwcG9ydC9kb2N1bWVudGF0aW9uL2FwcGxpY2F0aW9uX25vdGVzL3hhcHAzNzQucGRm.fnmeta1.pdf
www.xilinx.com/support/documentation/application_notes/xapp374.pdf

$
</pre>
<span id="The_code"><h3>The code</h3></span>
<p>`fnmeta.py` is licensed under the GPL and can be found ﻿﻿<a href="http://unsyncopated.com/corral/fnmeta.py">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2010/03/27/storing-file-metadata-with-fnmeta-py/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adding a dimension to your photos</title>
		<link>http://unsyncopated.com/blog/index.php/2010/03/09/adding-a-dimension-to-your-photos/</link>
		<comments>http://unsyncopated.com/blog/index.php/2010/03/09/adding-a-dimension-to-your-photos/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 20:13:47 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Shell programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>
		<category><![CDATA[Youtube]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2010/03/10/adding-a-dimension-to-your-photos/</guid>
		<description><![CDATA[Have you ever wanted to transform a run-of-the-mill photograph into a complete 3D scene automagically like Jack Black does in this mildly-NSFW 35MiB 2min clip from Enemy of the State? Well too bad -- it&#8217;s just not possible to ascertain details that are hidden from the camera&#8217;s view! You can get pretty close, though, with [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever wanted to transform a run-of-the-mill photograph into a complete 3D scene automagically like Jack Black does in <a href="http://unsyncopated.com/corral/enemy_of_the_state_trimmed.mpeg">this mildly-NSFW 35MiB 2min clip</a> from <a href="http://www.imdb.com/title/tt0120660/">Enemy of the State</a>?</p>
<p>Well too bad -- it&#8217;s just not possible to ascertain details that are hidden from the camera&#8217;s view!</p>
<p>You can get pretty close, though, with some software I discovered via <a href="http://www.linuxjournal.com/magazine/new-projects-fresh-labs-14">an article in the Linux Journal</a>.</p>
<p>						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4421405150"><img class="flickr small" title="Loctite Epoxy Bottle" alt="Loctite Epoxy Bottle" src="http://farm5.static.flickr.com/4002/4421405150_632821eaef_m.jpg" /></a></div>
					The software is called Discrete Geometry Viewer (DGV) and I&#8217;ll illustrate the salient feature with this photo I took of a cylindrical epoxy bottle:</p>
<p>GDV uses <a href="http://www.vtk.org/">the Visualization Toolkit (VTK)</a> to display what are called &#8220;surface plots&#8221;. I wanted to record a simple screencast of myself rotating a surface plot by hand but <a href="http://groups.google.com/group/discrete-geometry-viewer/browse_thread/thread/77df519c03d8eb6f">I couldn&#8217;t convince VTK to do &#8220;live&#8221; previews</a>. As a workaround I whipped up this shell script which rotates the surface plot in small increments, taking screenshots along the way:</p>
<pre class="brush: bash;">
# simulate multiple click-and-drag mouse events along predetermined

# coordinates. after each of these click-and-drag events, take a screenshot
# with imagemagick's &quot;import&quot; utility.

# you should generate coordinates at which to click with...
#  (while :; do xdotool getmouselocation | \
#   awk '{print substr($1,3) &quot; &quot; substr($2,3)}'; done) | uniq
# ... and save them to the file at COORDS_PATH

# you can assemble the screenshots into a movie with...
#  ffmpeg -r 30 -b 300k -i %05d.jpg -b 1157kb out.mp4

COORDS_PATH=~/prog/sh/screenshot_rect_while_dragging.dat
SHOTS_DIR=/media/humid_data/tmp/shots
# head -n1 ${COORDS_PATH} | read PREV_X PREV_Y
# PUZZLE: why doesnt the above work? instead we'll use...
PREV_X=343; PREV_Y=135
I=1
mkdir ${SHOTS_DIR}
while read CUR_X CUR_Y
do
  echo moving to ${CUR_X} ${CUR_Y} as step ${I}
  # move to pos
  # greets to fellow RIT alum jordan sissel, xdotool's author
  xdotool mousemove ${PREV_X} ${PREV_Y}
  # mouse down
  xdotool mousedown 1
  # move to pos
  xdotool mousemove ${CUR_X} ${CUR_Y}
  # mouse up
  xdotool mouseup 1
  # give the app some time to finish rendering
  sleep .3s
  # take screenshot
  import -crop 640x480+38+130 -window root -quality 100 \
  ${SHOTS_DIR}/$(printf &quot;%05d&quot; ${I}).jpg

  I=$((I+1))
  PREV_X=${CUR_X}
  PREV_Y=${CUR_Y}
done &lt; ${COORDS_PATH}
</pre>
<p>Next I assembled the screenshots into a video with <a href="http://www.openshotvideo.com/">Openshot</a>, a young but very stable and featureful nonlinear video editor. Here&#8217;s the result:</p>
<p>	<!-- Smart Youtube -->
	<span class="youtube">
		<object width="425" height="362">
			<param name="movie" value="http://www.youtube-nocookie.com/v/a4UCOrIZb2s&amp;rel=1&amp;color1=d6d6d6&amp;color2=f0f0f0&amp;border=1&amp;fs=1&amp;hl=en&amp;autoplay=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0" />
			<param name="allowFullScreen" value="true" />
			<embed wmode="transparent" 
				src="http://www.youtube-nocookie.com/v/a4UCOrIZb2s&amp;rel=1&amp;color1=d6d6d6&amp;color2=f0f0f0&amp;border=1&amp;fs=1&amp;hl=en&amp;autoplay=0&amp;showinfo=0&amp;iv_load_policy=3&amp;showsearch=0" 
				type="application/x-shockwave-flash" 
				allowfullscreen="true" 
				width="425" 
				height="362">
			</embed>
			<param name="wmode" value="transparent" />
		</object>
	</span><a href="http://www.youtube.com/watch?v=a4UCOrIZb2s">www.youtube.com/watch?v=a4UCOrIZb2s</a></p>
<p>For some more image-processing fanciness, see <a href="http://cs5.org/?p=147">this slick video demo of the &#8220;structural editing&#8221; tools planned for Photoshop CS5</a>. There&#8217;s interesting discussion (incl. some NSFW comments) at <a href="http://www.reddit.com/r/programming/comments/9o4uu/improved_image_editing_in_photoshop_cs5_demo/">this proggit thread</a>. For instructions on feeding &#8220;heightmaps&#8221; to a 3D printer, see <a href="http://www.thingiverse.com/thing:2078">these instructions</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2010/03/09/adding-a-dimension-to-your-photos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://unsyncopated.com/corral/enemy_of_the_state_trimmed.mpeg" length="35631104" type="video/mpeg" />
		</item>
		<item>
		<title>Sending data via cellular voice connections with Linux</title>
		<link>http://unsyncopated.com/blog/index.php/2009/11/19/sending-data-via-cellular-voice-connections-with-linux/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/11/19/sending-data-via-cellular-voice-connections-with-linux/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 10:45:03 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Footnotes]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Python programming]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Shell programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>
		<category><![CDATA[Table of Contents]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/11/20/sending-data-via-cellular-voice-connections-with-linux/</guid>
		<description><![CDATA[&#8220;A5/1 [the encryption scheme used in most cellular voice calls] has operated unchanged for the last 21 years but it has now reached its cryptographic end-of-life, engulfed by the march of Moore&#8217;s Law. However, the operational end-of-life of A5/1 may still be decades away as there are approximately 2 billion GSM subscribers, commanding about 80% of [...]]]></description>
			<content:encoded><![CDATA[<div>
<p style="padding-left: 30px;">&#8220;A5/1 [the encryption scheme used in most cellular voice calls] has operated unchanged for the last 21 years but it has now reached its cryptographic end-of-life, engulfed by the march of Moore&#8217;s Law. However, the operational end-of-life of A5/1 may still be decades away as there are approximately 2 billion GSM subscribers, commanding about 80% of the global mobile market. This would be a tough product recall indeed. A5/1 is well-positioned to become the NT of the mobile crypto world, and I see the makings of a long tail of GSM vulnerability.&#8221; - <a href="http://ch.linkedin.com/pub/luke-o-connor/1/bb6/152">Dr. Luke O&#8217;Connor</a> at <a href="http://lukenotricks.blogspot.com/2009/09/another-crack-at-open-rainbow-tables.html">NoTricks: Another crack at open Rainbow Tables for A5/1</a></p>
<div class='toc wptoc'>
<h2>Contents</h2>
<ol class='toc-odd level-1'>
	<li>
		<a href="#Introduction">Introduction</a>
	</li>
	<li>
		<a href="#The_modem__Hardware_components">The modem / Hardware components</a>
	</li>
	<li>
		<a href="#Transmitting_audio_from_a_PC_to_a_cell_phone__Software_components">Transmitting audio from a PC to a cell phone / Software components</a>
	</li>
	<li>
		<a href="#Demonstration__OKCrypto_scripts">Demonstration / OKCrypto scripts</a>
	</li>
	<li>
		<a href="#Encryption">Encryption</a>
	</li>
	<li>
		<a href="#Further_work">Further work</a>
	</li>
	<li>
		<a href="#What_I_learned">What I learned</a>
	</li>
	<li>
		<a href="#Conclusion__Download">Conclusion / Download</a>
	</li>
	<li>
		<a href="#Further_reading">Further reading</a>
	</li>
</ol>
</ol>
</ol>
</div>
<div class='wptoc-end'>&nbsp;</div>
<span id="Introduction"><h3>Introduction</h3></span>
<p>The ability to intercept and decrypt GSM cell phone conversations is now well within the reach of hobbyists.<sup>1</sup><sup>2</sup></p>
<p>My friend Scott and I were discussing this sobering fact one night and we began wondering if any systems exist which provide end-to-end encryption for this insecure link.</p>
<p>Sure, there are plenty of solutions for people with access to cellular dataconnections, but what can voice call participants use to foil eavesdroppers?</p>
<p>We didn&#8217;t find any low-cost systems so we decided to create our own. OKCrypto is the Linux-based encrypting software modem that we&#8217;ve made. It consists of two components: the modem component and crypto component.</p>
<span id="The_modem__Hardware_components"><h3>The modem / Hardware components</h3></span>
<p>We needed the ability to send data before we could try sending  encrypteddata, so the first step was to design a simple software modem.</p>
<p>Rather than executing the modem code on the cell phones themselves, I decided to host the modem code on a the sender and receiver&#8217;s Linux systems. This design provides two benefits:</p>
<ol>
<li>The modem code and crypto code has access to the rich Linux API.</li>
<li>Sensitive code and data are isolated from the both the cell phone itself and from the cell infrastructure. We have clean separation between trusted (PC) and untrusted (cell) environments.</li>
</ol>
<p>Thus, the &#8220;real work&#8221; in OKCrypto is done on the PC &#8211; the cell phones simply allow the PCs to talk to each other. See figure 1 for an overview of the hardware involved in the system. 						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4153181728"><img class="flickr small" title="Fig. 1 - Hardware components" alt="Fig. 1 - Hardware components" src="http://farm3.static.flickr.com/2534/4153181728_a0fe8e3a63_m.jpg" /></a></div>
					</p>
<p>Conceptually, the modem is similar to the analog Plain Old Telephone Service (POTS) modems from the Bad Old Days before broadband service became popular. Instead of an audio coupler, we&#8217;re using Bluetooth to connect our PC to our phone line. Instead of custom hardware, our modem is comprised of some glue scripts and the software packages they connect &#8211; all running on a Linux PC.</p>
<p>The modem doesn&#8217;t provide an asynchronous full-duplex communication link like traditional modems. This modem&#8217;s operation is simpler: The sender&#8217;s modem dials the number of, and subsequently transmits a pre-prepared chunk of data to, the recipient&#8217;s modem. It then hangs up.</p>
<p>The modem uses Dual-tone multi-frequency (DTMF) signaling to encode the data it transmits. I chose DTMF because I was familiar with it and because Debian provides a package for <a href="http://www.baycom.org/~tom/ham/linux/multimon.html">Multimon</a>. OKCrypto uses two utilities that Multimon provides:</p>
<ol>
<li>gen &#8211; a DTMF generation utility (digits-&gt;wav file)</li>
<li>multimon &#8211; a DTMF detection utility (wav file-&gt;digits)</li>
</ol>
<span id="Transmitting_audio_from_a_PC_to_a_cell_phone__Software_components"><h3>Transmitting audio from a PC to a cell phone / Software components</h3></span>
<p>I&#8217;d been working on a few Bluetooth security projects at the time, so the Hands-Free Profile (HFP)<sup>3</sup> came immediately to mind as a convenient way to transfer audio (and any data we&#8217;ve encoded in the audio) between a PC and a cell phone during a call.</p>
<p>-flickr size=&#8221;small&#8221; float=&#8221;right&#8221;-4153181752-/flickr-In most cases HFP is used to connect a a Bluetooth phone to a Bluetooth headset so that the headset can be used to make calls via the phone. See figure 2.</p>
<p>-flickr size=&#8221;small&#8221; float=&#8221;right&#8221;-4153181518-/flickr-In the PC world, HFP is typically used to connect a desktop computer to a bluetooth headset. See figure 3. In that configuration, the PC fulfills the first of two roles mandated by the HFP specification: the Audio Gateway (AG) role. The headset fulfills the hands-free (HF) role.</p>
						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4152393267"><img class="flickr small" title="Fig. 4 - PC ~ Cell phone" alt="Fig. 4 - PC ~ Cell phone" src="http://farm3.static.flickr.com/2737/4152393267_95526e2aaf_m.jpg" /></a></div>
					For our purposes, we need the PC to appear to be a bluetooth headset to a cell phone &#8211; the PC must fulfill the HF role. See figure 4. This is similar to how call-handling in-vehicle GPS/stereo units work.</p>
<p>Support for the HF role in <a href="http://www.bluez.org/">bluez</a>, the Linux Bluetooth stack (pronounced &#8220;blue-zee&#8221;), is just now maturing<sup>4</sup> so I went searching for a userspace implementation of the HFP protocol stack.</p>
<p>One of the best, chan_mobile, is distributed as an add-on to the popular open-source private branch exchange (PBX) <a href="http://www.asterisk.org/">Asterisk</a> system. If you configure chan_mobile to use your cell phone, Asterisk can make both outbound calls and receive inbound calls with the phone.</p>
<p>Asterisk is the largest software component of the OKCrypto modem. It not only provides a reliable HFP HF role implementation which works with a wide array of modern phones (see above), but also many essential telephony operations:</p>
<ol>
<li>Recording audio during a call. OKCrypto uses Asterisk&#8217;s built-in voicemail capabilities.</li>
<li>Transmitting audio during a call.</li>
<li>Pausing for a given time period.</li>
<li>Logging phone call details.</li>
</ol>
<p>See figure 5 for an overview of the software components in the OKCrypto system. Note that the same software is used on both the sender and receiver&#8217;s PCs.						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/4153379126"><img class="flickr small" title="Fig. 5 - Software components" alt="Fig. 5 - Software components" src="http://farm3.static.flickr.com/2521/4153379126_22a0fbc569_m.jpg" /></a></div>
					
<span id="Demonstration__OKCrypto_scripts"><h3>Demonstration / OKCrypto scripts</h3></span>
<p>Let&#8217;s look at how we can use this modem to send a 16-byte binary file over a cellular voice connection.</p>
<p>First, the sender and recipient will need to perform some set-up steps:</p>
<ol>
<li>1. Acquire a Linux-supported computer and Bluetooth adapter. I found that using a virtual machine introduces latency that bluez/btusb cannot tolerate.</li>
<li>Acquire a HFP-capable cell phone.</li>
<li>Install Linux, <a href="http://sox.sourceforge.net/">SoX</a>, Python, multimon, Asterisk, the Asterisk &#8220;add-ons&#8221;, GPG, and the OKCrypto scripts.</li>
<li>Pair cell phone with computer. Grant HFP access.</li>
<li>Configure chan_mobile</li>
<li>Start Asterisk Next, the sender can issue this command at a shell to send the file &#8216;/tmp/foo&#8217; to the recipient at 585-555-3258.
<pre class="brush: bash;">$ ./bin_to_int_seq.py /tmp/foo | ./ast_send.sh 5855553258 [...]
$ cksum /tmp/foo 668417501 16 /tmp/foo</pre>
<p>She&#8217;ll notice her PC making a call with her phone, silently transmitting the data, and disconnecting. Behind the scenes, the OKCrypto scripts will&#8230;</li>
<li>Convert the bytes in /tmp/foo to a series of decimal digits.</li>
<li>Encode the digits as DTMF tones with gen from the multimon package. 1. Increase the pitch (time-independent) to prevent any intermediary systems (esp. Asterisk) from interpreting the tones.</li>
<li>Queue the final audio file for transmission by Asterisk.</li>
</ol>
<p>The recipient will hear his phone ring once before his PC answers the call, records the audio, and disconnects. When the call is complete, Asterisk will invoke one of the OKCrypto scripts to&#8230;</p>
<ol>
<li>Decrease the pitch to yield the original DTMF tones.</li>
<li>Decode the DTMF tones to a series of decimal digits.</li>
<li>Convert the digits to a series of bytes which is written to &#8216;/tmp/bar&#8217;.
<pre class="brush: bash;">$ tr -d '\n' &lt; /tmp/newest_vm.txt | ./int_seq_to_bin.py /tmp/bar [...]
$ cksum /tmp/bar 668417501 16 /tmp/bar</pre>
</li>
</ol>
<span id="Encryption"><h3>Encryption</h3></span>
<p>Now that we can reliably send data, let&#8217;s make sure that it&#8217;s encrypted first. This turns out to be one of the simplest components of the system &#8211; many good crypto APIs are available.</p>
<p>I use <a href="http://www.gnupg.org/">GnuPG</a>:</p>
<pre class="brush: bash;">$ gpg --symmetric --force-mdc --cipher-algo AES256 filetoencrypt </pre>
<p>The `&#8211;force-mdc` option provides integrity checking &#8211; useful for handling transmission errors. Consider these GPG options carefully and make sure they fit your requirements.</p>
<span id="Further_work"><h3>Further work</h3></span>
<p>Here are a few ideas we&#8217;re pursuing for the future of this project:</p>
<ul>
<li>Moving the modem code to the cell phone. This would simplify the setup but potentially risk security.</li>
<li>Improving modem error rate. Data is often erroneously duplicated during transmission.</li>
<li>Increasing the modem throughput. The current code averages a meager 10 bytes/second.</li>
<li>Hiding the data within a steganographic channel in a normal voice conversation.</li>
<li>Incorporating GPG into the OKCrypto scripts.</li>
<li>Packaging the system as a LiveCD/Live flash drive.</li>
<li>Implementing key exchange.</li>
<li>Building an embedded device dedicated to OKCrypto.</li>
</ul>
<span id="What_I_learned"><h3>What I learned</h3></span>
<p>I gained experience in the follow areas during the design, implementation. and testing:</p>
<ul>
<li>GSM, CDMA crypto. I suspect the cellular phone industry would make a great case study in protocol security by obscurity.</li>
<li>Cellular voice codecs used by large carriers. Trivia: your calls only require ~10kbps.<sup>5</sup></li>
<li>Bluetooth HFP specification and available implementations.</li>
<li>Debugging latency tolerances in virtual machine USB &#8220;passthrough&#8221; subsystems.</li>
<li>The <a href="http://www.twilio.com/">Twilio</a> telephony API. I used Twilio when I only had one cell phone to debug with.</li>
<li>Asterisk administration.</li>
</ul>
<span id="Conclusion__Download"><h3>Conclusion / Download</h3></span>
<p>I&#8217;ve described a method to securely transmit data over any of the widely-available cell voice networks. The implementation requires only commodity hardware, open-source software, and minimal setup.</p>
<p>Be aware that transmitting data by &#8220;automated means&#8221; may violate the terms of your cellular service contract. I disclaim all liability. This information is provided for educational purposes only.</p>
<p>You can download the OKCrypto system here: http://www.unsyncopated.com/corral/okcrypto_v0.1.tar.gz</p>
<p>It is licensed under the LGPL.</p>
<span id="Further_reading"><h3>Further reading</h3></span>
<ul>
<li>You&#8217;ll find lots of links to cell security architecture articles, Bluetooth HFP implementations, and Asterisk administration web pages on the wiki at <a href="http://www.unsyncopated.com/wiki/Crypto%20Phone/Stacked%20Linux-based%20CPhone%20Brainstorming">Crypto Phone/Stacked Linux-based CPhone Brainstorming</a></li>
</ul>
<p>Update 1/13/09 - Check out some technical notes on our recent progress with a faster and more reliable modem: <a href="https://www.unsyncopated.com/wiki/OKCrypto/Progress%20Report%20for%2001-09-2010">OKCrypto/Progress Report for 01-09-2010</a></p>
</div>
<ol class="footnotes">
<li id="footnote_0_317" class="footnote"><a href="http://spectrum.ieee.org/telecom/wireless/open-source-effort-to-hack-gsm">Open-Source Effort to Hack GSM</a> John Blau &#8211; IEEE Spectrum Magazine &#8211; December 2009 issue</li>
<li id="footnote_1_317" class="footnote"><a href="https://har2009.org/program/attachments/119_GSM.A51.Cracking.Nohl.pdf">Subverting the security base of GSM</a> Karsten Nohl &#8211; Hacking at Random &#8211; 8/15/2009</li>
<li id="footnote_2_317" class="footnote"><a href="http://www.bluetooth.com/Bluetooth/Technology/Works/HFP.htm">Bluetooth Hands-Free Profile (HFP) 1.5</a> &#8211; Bluetooth Special Interest Group &#8211; 11/25/2005</li>
<li id="footnote_3_317" class="footnote"><a href="https://bugs.maemo.org/show_bug.cgi?id=2754#c1">Comment #1 on Maemo bug #2754</a> &#8211; Johan Hedberg &#8211; 1/25/2009</li>
<li id="footnote_4_317" class="footnote"><a href="http://en.wikipedia.org/w/index.php?title=Adaptive_Multi-Rate_audio_codec&amp;oldid=327719647">Adaptive Multi-Rate audio codec</a> &#8211; Wikipedia &#8211; 11/24/2009</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/11/19/sending-data-via-cellular-voice-connections-with-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>good.net is fast.com</title>
		<link>http://unsyncopated.com/blog/index.php/2009/02/24/goodnet-is-fastcom/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/02/24/goodnet-is-fastcom/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 16:34:57 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Footnotes]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Shell programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/02/24/goodnet-is-fastcom/</guid>
		<description><![CDATA[good.net is a stripped-down file-hosting service (cf. drop.io/sendthisfile.com)1 that has four &#8220;new-to-me&#8221; features:2 You can earn money when people download your files via their affiliate program. Your audience can access your files via HTTPS. An honest dedication to free speech and free software. You can upload your files via FTP-over-explicit-SSL (FTPES). Their support page doesn&#8217;t list [...]]]></description>
			<content:encoded><![CDATA[						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/docsearls/2440194966"><img class="flickr small" title="2008_04_biketrail_infrastructure_016" alt="2008_04_biketrail_infrastructure_016" src="http://farm3.static.flickr.com/2133/2440194966_ec0face197_m.jpg" /></a></div>
					<br />
<a href="http://good.net/">good.net</a> is a stripped-down file-hosting service (cf. <a href="http://www.drop.io">drop.io</a>/<a href="http://www.sendthisfile.com">sendthisfile.com</a>)<sup>1</sup> that has four &#8220;new-to-me&#8221; features:<sup>2</sup></p>
<ul>
<li>You can earn money when people download your files via <a href="http://good.net/affiliate/">their affiliate program</a>.</li>
<li>Your audience can access your files via HTTPS.</li>
<li>An honest <a href="https://good.net/about/">dedication to free speech and free software</a>.</li>
<li>You can upload your files via FTP-over-explicit-SSL (FTPES). <a href="http://good.net/support/">Their support page</a> doesn&#8217;t list their FTPES host key fingerprint but you &#8221;can&#8221; just barely see it at 0m36s on their <a href="http://good.net/support/filezilla.html">FileZilla support page</a>. <strong>Update:</strong> they&#8217;ve posted <a href="https://forums.good.net/phpBB/viewtopic.php?f=4&amp;t=6&amp;sid=a6c80c76bc9054ac1a3a51e7f313b3a1">the fingerprint in their support forum</a>. See <a href="http://unsyncopated.com/wiki/Secure good.net FTP uploads with lftp">my notes on uploading with lftp(1)</a> for more info on securing your CLI FTP transactions.</li>
</ul>
<p>Their servers are also hooked up to especially fat pipes. I get 5 megabytes/sec sustained with my Thinkpad T30&#8242;s wired NIC on RIT&#8217;s library network. I got <em>10</em> megabytes/sec with my <a href="http://www.rimuhosting.com">Rimuhosting</a> VPS in their <a href="http://rimuhosting.com/datacenters.jsp#a3">Level(3) and Abovenet</a>-connected datacenter.</p>
<span id="Backstory"><h3>Backstory</h3></span>
<p>						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/3308794151"><img class="flickr small" title="Openmoko guru Harald Welte at 25C3" alt="Openmoko guru Harald Welte at 25C3" src="http://farm4.static.flickr.com/3374/3308794151_8d3c79147a_m.jpg" /></a></div>
					
<p>I found good.net via a link in <a href="http://www.mcgrewsecurity.com/2008/09/11/black-hat-usa-2008-and-defcon-16-audio-available/">the McGrew Security blog</a> to <a href="https://avondale.good.net/dl/bd/">good.net&#8217;s mirror</a> of <a href="http://darkoz.com/">DarkOz</a>&#8216;s <em>giant</em> collection of security conference videos &#8211; the &#8220;Hacker Media Archive&#8221;.</p>
<p>The Archive&#8217;s <a href="https://avondale.good.net/dl/bd/25c3/video_h264_720x576/">25th Chaos Communication Congress (25C3) videos</a> alone occupy nearly 40GB&#8230;</p>
<pre class="brush: bash;">

$ curl --silent http://avondale.good.net/dl/bd/25c3/video_h264_720x576/ |
awk --assign i=0 '/.mp4&quot;/{i=i+substr($8, 1, length($8)-1);} END {print i}'

39175
</pre>
<p>						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/3309623054"><img class="flickr small" title="Tor Project co-founder Roger Dingledine at 25C3" alt="Tor Project co-founder Roger Dingledine at 25C3" src="http://farm4.static.flickr.com/3039/3309623054_268ec04272_m.jpg" /></a></div>
					<br />
I&#8217;ve included two screen captures from the <a href="http://creativecommons.org/licenses/by-nc-nd/2.0/">freely-licensed</a> h264-encoded 720&#215;576 25C3 videos at right.</p>
<p>In addition to the CCC videos, you can find footage and materials from DEFCON, HOPE, Black Hat, CodeCon, DeepSec, HITB, NOTACON, PhreakNIC,  REcon, Shmoocon, and ToorCon. Phew!
<ol class="footnotes">
<li id="footnote_0_128" class="footnote">If you&#8217;re looking for a more &#8221;active&#8221; filesharing tool, one that syncs files across machines for you, try <a href="http://www.getdropbox.com">Dropbox</a> as recommended by an <a href="http://www.imdb.com/name/nm1168932/bio">aspiring grocer</a> friend of mine. They&#8217;ve even got a Linux client.</li>
<li id="footnote_1_128" class="footnote">Yes, the above manhole cover photo was taken by <a href="http://blogs.law.harvard.edu/doc/">the Doc Searls of Linux Journal fame</a>.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/02/24/goodnet-is-fastcom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Bash &#8220;edit-in-place&#8221; idiom</title>
		<link>http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/</link>
		<comments>http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 12:48:43 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/</guid>
		<description><![CDATA[I use a shell script called `stream.sh` to launch my music player and open a given internet radio station. I use it like this to tune to a local AM station: $ stream.sh 1370 I usually edit small scripts like that with `nano(1)`. Rather than type the entire path to the script when I need [...]]]></description>
			<content:encoded><![CDATA[<p>I use a shell script called `stream.sh` to launch my music player and open a given internet radio station. I use it like this to tune to a local AM station:</p>
<pre class="brush: bash;">

$ stream.sh 1370
</pre>
<p>I usually edit small scripts like that with `nano(1)`. Rather than type the entire path to the script when I need to edit it (`nano ~/prog/sh/stream.sh`) I just say `nano $(which stream.sh)` i.e. &#8220;edit whichever file is in the `$PATH` with that name&#8221;. 						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/scoobyfoo/268948449"><img class="flickr small" title="Repairs" alt="Repairs" src="http://farm1.static.flickr.com/83/268948449_6204a3eae5_m.jpg" /></a></div>
					My shell (`zsh(1)`) performs tab-completion on the single argument to `which(1)` &#8211; here, &#8220;stream.sh&#8221;. So I&#8217;ve got &#8220;nano $(which stre_.s_)&#8221; where &#8220;_&#8221;s are tabs.</p>
<p>It&#8217;s actually a brain-saver with more verbose names, I promise `:]`.</p>
<span id="Blogged_to8230"><h3>Blogged to&#8230;</h3></span>
<p>&#8220;Step by Step&#8221; by Chronos on <a href="http://www.di.fm">di.fm</a>&#8216;s chillout station as recommended by <a href="http://www.mixstation.net/comment.php?dlid=2713&amp;ENGINEsessID=3c9d4fb2b462f91616237e2819581684">DJ JMULV</a></p>
<span id="See_also"><h3>See also</h3></span>
<ul>
<li><span style="font-size: 13.3333px;"><a href="http://www.google.com/search?q=&quot;Writing+Zsh+Completion+Functions&quot;">An article on Zsh(1) completion</a> from Linux Magazine</span></li>
<li><span style="font-size: 13.3333px;"><a href="http://michael-prokop.at/blog/2008/12/19/mikas-advent-calendar-day-19-zsh-completion/">mikas blog &#8211; Blog Archive &#8211; mika&#8217;s advent calendar &#8211; day 19: zsh completion</a></span></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2009/02/19/a-bash-edit-in-place-idiom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Editing files as root with Emacs and Tramp</title>
		<link>http://unsyncopated.com/blog/index.php/2007/09/09/editing-files-as-root-with-emacs-and-tramp/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/09/09/editing-files-as-root-with-emacs-and-tramp/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 00:50:42 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Emacs]]></category>
		<category><![CDATA[Shell programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=723</guid>
		<description><![CDATA[Did you know that you can use an existing non-privileged instance of Emacs to open files as root? Yep, Emacs includes a module called TRAMP which can use sudo to read and write files. As is usually the case, I had to work sweat a little to make it work. My problem was that my [...]]]></description>
			<content:encoded><![CDATA[<p>Did you know that you can use an existing non-privileged instance of Emacs to open files as root? Yep, Emacs includes a module called <a href="http://www.emacswiki.org/cgi-bin/wiki/TrampMode">TRAMP</a> which can use sudo to read and write files.</p>
<p>As is usually the case, I had to work sweat a little to make it work. My problem was that my zsh prompt was too fancy. The solution was to toss this conditional in at the end of my .zshrc:</p>
<pre class="brush: bash;">

if [ $TERM = &quot;dumb&quot; ]; then
   unsetopt zle
   export PS1=&quot;%% &quot;
fi
</pre>
<p>This works by disabling the zsh line editor (&#8220;zle&#8221;) and setting a plain vanilla prompt (&#8220;PS1&#8243;) that tramp can recognize when it logs in.</p>
<p>TRAMP is a little slow on my machine but it sure beats firing up a new Emacs instance every time I want to edit `/etc/superdooper.conf`</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/09/09/editing-files-as-root-with-emacs-and-tramp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Omitting Certain Commands from zsh&#8217;s History</title>
		<link>http://unsyncopated.com/blog/index.php/2007/08/18/omitting-certain-commands-from-zshs-history/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/08/18/omitting-certain-commands-from-zshs-history/#comments</comments>
		<pubDate>Sat, 18 Aug 2007 19:02:52 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Security]]></category>
		<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=763</guid>
		<description><![CDATA[I use pwsafe to store passwords on Ubuntu. It&#8217;s a *nix command line port of Counterpane&#8217;s Password Safe which uses twofish to store passwords in a database file. You can find it in the Ubuntu universe repository. If someone somehow managed to get ahold of my shell&#8217;s history file, they&#8217;d get a lot of juicy [...]]]></description>
			<content:encoded><![CDATA[<p>I use <a href="http://nsd.dyndns.org/pwsafe/">pwsafe</a> to store passwords on Ubuntu. It&#8217;s a *nix command line port of Counterpane&#8217;s <a href="http://passwordsafe.sourceforge.net/">Password Safe</a> which uses <a href="http://en.wikipedia.org/wiki/Twofish">twofish</a> to store passwords in a database file. You can find it in the Ubuntu universe repository.</p>
<p><span style="font-size: 13.3333px;">If someone somehow managed to get ahold of my shell&#8217;s history file, they&#8217;d get a lot of juicy info like:</span></p>
<ul>
<li>What system and web accounts I have.</li>
<li>The names I used for my accounts which might be helpful in the cryptoanalysis of my pwsafe database.</li>
</ul>
<p>So what I&#8217;ve done is set up zsh, my shell, to <em>not</em> save invocations of pwsafe in my history. With the &#8220;HIST_IGNORE_SPACE&#8221; option, you can tell zsh to ignore commands that begin with a space. I did this for a while but found myself forgetting to type the space sometimes. The trick is to set up an alias which includes a leading space:</p>
<blockquote>
<pre>alias pwsafe=" pwsafe"</pre>
</blockquote>
<p>So now whenever I run something like</p>
<blockquote>
<pre>pwsafe -l ubuntu.forums -up</pre>
</blockquote>
<p>it won&#8217;t get saved to the history file.</p>
<span id="Further_reading"><h3>Further reading</h3></span>
<ul>
<li>The Z-Shell Manual &#8211; <a href="http://zsh.sourceforge.net/Doc/Release/Options.html#SEC105">16.2.4: History options</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/08/18/omitting-certain-commands-from-zshs-history/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Determining who acted in two known films</title>
		<link>http://unsyncopated.com/blog/index.php/2007/08/18/determining-who-acted-in-two-known-films/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/08/18/determining-who-acted-in-two-known-films/#comments</comments>
		<pubDate>Sat, 18 Aug 2007 06:13:06 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Flickr]]></category>
		<category><![CDATA[Shell programming]]></category>
		<category><![CDATA[Syntax highlighter]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/index.php/2009/02/28/determining-who-acted-in-two-known-films/</guid>
		<description><![CDATA[Have you ever seen someone in a movie and thought to yourself &#8220;Hey, weren&#8217;t they in movie Y too?&#8221; This happened to me last night when I was watching &#8221;Casino&#8221;. The parking lot attendant from a certain scene looked just like a character from &#8221;Fear and Loathing in Las Vegas&#8221;. To the *nix shell, Robin!&#60;/Bruce [...]]]></description>
			<content:encoded><![CDATA[<p>						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/3316942898"><img class="flickr small" title="Just take the ticket!" alt="Just take the ticket!" src="http://farm4.static.flickr.com/3401/3316942898_1c48506dd5_m.jpg" /></a></div>
					Have you ever seen someone in a movie and thought to yourself &#8220;Hey, weren&#8217;t they in movie Y too?&#8221;</p>
<p>This happened to me last night when I was watching &#8221;Casino&#8221;. The parking lot attendant from a certain scene looked just like a character from &#8221;Fear and Loathing in Las Vegas&#8221;.</p>
<p>To the *nix shell, Robin!&lt;/Bruce Wayne Voice&gt;</p>
<p>I wrote a short script to download the IMDb &#8220;profile&#8221; pages for all the actors in movie X and list which ones also acted in movie Y. This is, effectively, a <a href="http://math.comsci.us/sets/intersection.html">set intersection</a> operation.</p>
<p>I could&#8217;ve registered for IMDb&#8217;s 14-day trial of their $20/mo &#8220;<a href="http://pro.imdb.com/about/a2z">Pro</a>&#8221; service which allows advanced searches on their database, but I wanted a challenge.</p>
<p>Here are the important pieces of the script:</p>
<pre class="brush: bash;">

# grab (only) the profile pages for each actor who performed in title
# 'tt0112641' ('casino'). recurse, but only 1 level deep into links.
wget --recursive --level=1 --wait=1 --include_directories=/names
'http://www.imdb.com/title/tt0112641/fullcredits'

# determine if any of the retrieved profile pages contain a reference
# to 'fear and loathing'
find . -type f -print | xargs grep --files-with-matches
--ignore-case 'fear and loathing'
</pre>
<p>						<div class="flickr-gallery image right"><a href="http://www.flickr.com/photos/55502932@N00/3317046420"><img class="flickr small" title="They're just checking in now" alt="They're just checking in now" src="http://farm4.static.flickr.com/3358/3317046420_c7167bd824_m.jpg" /></a></div>
					<br />
wget will, by default, obey a site&#8217;s robots.txt file. IMDb.com&#8217;s robots.txt says you&#8217;ll get fined 1 cent for every request to their server that causes a denial of service! So, be nice and only download from the crawl-able portions of their site (and do it slowly with `&#8211;wait`, otherwise you might get temporalily blocked with HTTP 500 errors).</p>
<p>The script gave me ~10 results most of which were off-screen roles e.g. &#8220;set designer&#8221;. One, however, was the dude I was looking for: <a href="http://www.imdb.com/name/nm0494040/">Brian LeBaron</a>!. He acted as a parking attendant in both Casino and Fear and Loathing.</p>
<p><strong>Update: </strong>There are now <em>much</em> more elegant ways to interact with IMDb. See, for example, <a href="http://imdbpy.sourceforge.net/">IMDbPY</a></p>
<p><strong>Update:</strong> More retrospection: the &#8220;combine&#8221; utility in <a href="http://debaday.debian.net/2007/04/15/moreutils-a-collection-of-useful-command-line-tools/">moreutils (via deb-a-day</a>) might&#8217;ve been handy.</p>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/08/18/determining-who-acted-in-two-known-films/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Saving piped output with less</title>
		<link>http://unsyncopated.com/blog/index.php/2007/07/11/saving-piped-output-with-less/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/07/11/saving-piped-output-with-less/#comments</comments>
		<pubDate>Wed, 11 Jul 2007 21:16:36 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=706</guid>
		<description><![CDATA[The problem You&#8217;ve piped the lengthy output of some command to your pager, less. As you&#8217;re scrolling through the output you realize you&#8217;d like to save it to disk. The output took a long time to generate, so you don&#8217;t want to re-run the original command just to redirect the output to a file. Your [...]]]></description>
			<content:encoded><![CDATA[<span id="The_problem"><h3>The problem</h3></span>
<p>You&#8217;ve piped the lengthy output of some command to your pager, less. As you&#8217;re scrolling through the output you realize you&#8217;d like to save it to disk. The output took a long time to generate, so you don&#8217;t want to re-run the original command just to redirect the output to a file.</p>
<p>Your first instinct might be to press &#8216;v&#8217; to edit the output with $EDITOR. less will balk &#8220;Cannot edit standard input (press RETURN)&#8221;.</p>
<span id="The_solution"><h3>The solution</h3></span>
<p>The solution is to use less&#8217; &#8220;|&#8221; command key to pipe the output to tee which will write it to a file. See the &#8220;Commands&#8221; section in LESS(1) for the full syntax of this command. Pressing the &#8216;h&#8217; command key for &#8220;help&#8221; will give an abbreviated syntax under its &#8220;MISCELLANEOUS COMMANDS&#8221; section:</p>
<blockquote>
<pre>"|Xcommand   Pipe file between current pos &amp; mark X to shell command."</pre>
</blockquote>
<p>You want to pipe the<em> entire buffer</em> to a file so first press &#8220;g&#8221; to go to the first line. Next, press the &#8220;|&#8221; key followed by &#8220;$&#8221; to indicate you want to pipe right up until the end of the buffer. &#8220;$&#8221; is a predefined mark for the end of the file. Lastly, type &#8220;tee&#8221; followed by a space and the name of the file you&#8217;d like to save to.</p>
<p>So, from anywhere in a less buffer, you can type the following to save the buffer to a file named foo.txt:</p>
<blockquote>
<pre>g|$tee foo.txt</pre>
</blockquote>
<p>you&#8217;ll see &#8220;|done (press RETURN)&#8221;.</p>
<span id="Further_reading_"><h3>Further reading </h3></span>
<ul>
<li>LESS(1) &#8211;log-file</li>
<li>git-diff-tree(1) &#8211;pickaxe-regex</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/07/11/saving-piped-output-with-less/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recalling a word from the current command line</title>
		<link>http://unsyncopated.com/blog/index.php/2007/04/22/recalling-a-word-from-the-current-command-line/</link>
		<comments>http://unsyncopated.com/blog/index.php/2007/04/22/recalling-a-word-from-the-current-command-line/#comments</comments>
		<pubDate>Sun, 22 Apr 2007 17:29:46 +0000</pubDate>
		<dc:creator>Tyler</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Shell programming]]></category>

		<guid isPermaLink="false">http://unsyncopated.com/blog/?p=668</guid>
		<description><![CDATA[I often find myself using a command like this to make a backup of a file: cp /etc/slop/gunk.conf /etc/slop/gunk.conf_before_v2_upgrade Since the first portion of the second argument is always the same as the first argument (the green text), it bugged me to have to do tab completion for it. Luckily, zsh and bash provide an [...]]]></description>
			<content:encoded><![CDATA[<p>I often find myself using a command like this to make a backup of a file:</p>
<blockquote>
<pre>cp <span style="color: #008000;">/etc/slop/gunk.conf</span> <span style="color: #008000;">/etc/slop/gunk.conf</span>_before_v2_upgrade</pre>
</blockquote>
<p>Since the first portion of the second argument is always the same as the first argument (the green text), it bugged me to have to do tab completion for it. Luckily, zsh and bash provide an event designator for the current command line (ie the one you&#8217;re currently typing). It is !# and it works just like the other events (eg !! is the previous command). See <a href="http://zsh.dotsrc.org/Doc/Release/zsh_13.html#SEC48">Zsh Documentation &#8211; History Expansion.</a> Bash&#8217;s syntax is very similar.</p>
<p>So now when I want to make a crude backup like above, I use something like this:</p>
<blockquote>
<pre>cp /etc/slop/gunk.conf !#:1_before_v2_upgrade</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://unsyncopated.com/blog/index.php/2007/04/22/recalling-a-word-from-the-current-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

