<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title type="text">good coders code, great reuse</title>
  <id>http://www.catonmat.net/feed</id>
  <updated>2010-08-30T18:23:07Z</updated>
  <link href="http://www.catonmat.net" />
  
  <author>
    <name>Peteris Krumins</name>
    <uri>http://www.catonmat.net/about</uri>
    <email>peter@catonmat.net</email>
  </author>
  <subtitle type="text">Peteris Krumins' blog about programming, hacking, software reuse, software ideas, computer security, google and technology.</subtitle>
  <icon>http://www.catonmat.net/favicon.ico</icon>
  <generator uri="http://www.catonmat.net" version="v1.0">catonmat blog</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/catonmat" /><feedburner:info uri="catonmat" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>catonmat</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Reflections on Node.js Knockout Competition</title>
    <id>237</id>
    <updated>2010-08-30T18:23:07Z</updated>
    <published>2010-08-30T18:50:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/7CGefS4mtHY/node-js-knockout-competition" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nTIgB8xJmAHfBKDvv2UWR2bCB6Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nTIgB8xJmAHfBKDvv2UWR2bCB6Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nTIgB8xJmAHfBKDvv2UWR2bCB6Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nTIgB8xJmAHfBKDvv2UWR2bCB6Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;So I participated in the 48 hour &lt;a href="http://nodeknockout.com/"&gt;Node.js Knockout&lt;/a&gt; competition together with &lt;a href="http://substack.net"&gt;James Halliday&lt;/a&gt; and &lt;a href="http://jesusabdullah.github.com/"&gt;Joshua Holbrook&lt;/a&gt;. Our team was called &lt;a href="http://nodeknockout.com/teams/dark-knights"&gt;Dark Knights&lt;/a&gt; and we created an online chess application called &lt;a href="http://dark-knights.no.de"&gt;Node Chess&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We didn't quite manage to completely finish the game and it has several bugs, like the turns don't alternate and the king can be captured, but it's crazy awesome anyway. If both players follow the rules, it all works correctly. Castling works, pawn promotion works, capture en-passant also. &lt;a href="http://dark-knights.no.de"&gt;Try it&lt;/a&gt; and if you find it awesome, please &lt;a href="http://nodeknockout.com/teams/dark-knights#your_vote"&gt;vote&lt;/a&gt;! Oh, and it works only Chrome. Ancient-browsers-please-be-gone!&lt;/p&gt;
&lt;p&gt;Here is how the game looks,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="/images/reflections-nodeko/node-chess.gif"&gt;&lt;br&gt;
&lt;small&gt;A chess game between pkrumins and someone. King's Indian Defence.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Joshua did all the awesome vector graphics work. I did the chess engine work, and James used his amazing &lt;a href="http://github.com/substack/dnode"&gt;dnode node.js module&lt;/a&gt; to blend client and server code together. James has actually redefined how web development happens. Instead of writing server code and client code, as we are so used to, with his dnode framework it's now possible to use the same code both server and client side! Much less hustle and purely ingenious!&lt;/p&gt;
&lt;p&gt;Here is the same game in perspective view, the highlighted squares are the available moves,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="/images/reflections-nodeko/node-chess-perspective.gif"&gt;&lt;br&gt;
&lt;small&gt;The same game in perspective view.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;And the moves are animated, too! The pawns shoot the opponent pieces and the queen stabs them. &lt;a href="http://dark-knights.no.de/"&gt;Try it&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Right, so my reflections on the competition.&lt;/p&gt;
&lt;p&gt;It was well organized, and we were sent access to a &lt;a href="http://www.joyent.com/"&gt;Joyent&lt;/a&gt; deployment server and a &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt; server early on together with instructions. It turned out that Heroku's didn't support &lt;a href="http://github.com/LearnBoost/Socket.IO"&gt;Socket.IO&lt;/a&gt; or websockets. Win for Joyent. Pretty much everyone went with Joyent as far as I know. We had some technical difficulties at the start with deploying our code, but guys at #node.js helped us and we got our app running pretty quickly.&lt;/p&gt;
&lt;p&gt;We used 3 Git repositories to push the code to, our own GitHub repositories (&lt;a href="http://github.com/pkrumins/node-chess"&gt;pkrumins&lt;/a&gt;, &lt;a href="http://github.com/substack/node-chess"&gt;substack&lt;/a&gt;, &lt;a href="http://github.com/jesusabdullah/node-chess"&gt;jesusabdullah&lt;/a&gt;), then the node knockout's private repository for judges, and deployment repository on Joyent. Joyent was configured so that as you push your code to its Git repo, the hooks in it would restart the node.js service and the you'd be instantly running the latest version of your code.&lt;/p&gt;
&lt;p&gt;So I'd make changes push to my GitHub repo, James would pull from me. He'd make changes, I'd pull from him, and same for Joshua. It went pretty flawless. We had like 12 merge errors total, but those were all resolved within a minute or two.&lt;/p&gt;
&lt;p&gt;Now some numbers. We're actually amazed by our performance. Check out these numbers:&lt;/p&gt;
&lt;pre &gt;
$ git log | grep Author | wc -l
429
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;429 commits&lt;/strong&gt;! Can you believe that? 429 commits in 2 days! That's 9 commits per hour on average! That is what I call hacking!&lt;/p&gt;
&lt;p&gt;My commits:&lt;/p&gt;
&lt;pre &gt;
$ git log | grep Author | grep Peteris | wc -l
169
&lt;/pre&gt;
&lt;p&gt;I did 3.5 commits per hour on average. And funnily, James and Joshua each had 130 commits:&lt;/p&gt;
&lt;pre &gt;
$ git log | grep Author | grep James | wc -l
130
$ git log | grep Author | grep Joshua | wc -l
130
&lt;/pre&gt;
&lt;p&gt;That's 2.7 commits per hour on average! Amazing! But we also slept between the competition days. On the both days we did about 4 hours of clean sleep, shrinking our competition time to 40 hours. Then our average becomes &lt;strong&gt;10.7 commits per hour&lt;/strong&gt;! Wowsers!&lt;/p&gt;
&lt;p&gt;Here is a graph, made with &lt;a href="http://raphaeljs.com/"&gt;Raphael.js&lt;/a&gt;, that shows our &lt;code&gt;git commit&lt;/code&gt; activity by hour, starting from 3am UTC Aug 28 to 3am UTC Aug 30:&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="/images/reflections-nodeko/git-commit-activity.gif"&gt;&lt;br&gt;
&lt;small&gt;Team "Dark Knights" git commit activity by hour.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Our peak commit intensity was at 9pm the last night, when we did 23 commits in one hour. Our team was also widely spread out. I am in Riga, Latvia, James is in Kenai, Alaska, and Joshua is in Fairbanks, Alaska. Yet we managed to keep the same schedule. I'd go to bed at noon (noon for me is 3pm UTC, see the graph above), while James and Joshua at midnight, and we'd wake up several hours later and keep hacking!&lt;/p&gt;
&lt;p&gt;Total number of code lines written:&lt;/p&gt;
&lt;pre &gt;
$ wc -l `find . -name '*.js' -o -name '*.html' -o -name '*.css' | \
  egrep -v '(jquery|raphael)'`
3074 total
&lt;/pre&gt;
&lt;p&gt;So we wrote 3074 lines in two days, which according to git break up into added vs. deleted as following:&lt;/p&gt;
&lt;pre &gt;
$ git log --numstat | grep '^[0-9]' | \
  egrep '(\.js|\.css|\.html|jquery|raphael)' | \
  awk '{a+=$1;d+=$2}END{print "Added: " a, "Deleted: " d}'
Added: 5210 Deleted: 2042
&lt;/pre&gt;
&lt;p&gt;Hmm, 5210-2042 doesn't quite add up to 3074 but is close enough. From these 3074 lines of code non-empty were:&lt;/p&gt;
&lt;pre &gt;
$ cat `find . -name '*.js' -o -name '*.html' -o -name '*.css' | \
  egrep -v '(jquery|raphael)'` | perl -nle 'print if /\S/' | \
  wc -l
2659
&lt;/pre&gt;
&lt;p&gt;So 2659 real lines of code in 2 days! Talk about productivity! And that's just code alone. Joshua also did 50 artworks,&lt;/p&gt;
&lt;pre &gt;
$ find . -name '*.svg' -o -name '*.png' | wc -l
50
&lt;/pre&gt;
&lt;p&gt;Total number of file changes:&lt;/p&gt;
&lt;pre &gt;
$ git log --shortstat | grep 'files changed' | \
  awk '{t+=$1}END{print t}'  
724
&lt;/pre&gt;
&lt;p&gt;We communicated in IRC, in our #stackvm &lt;a href="http://www.catonmat.net/blog/i-am-doing-a-startup/"&gt;startup&lt;/a&gt; channel. Here are some statistics on how much stuff went on in our IRC channel:&lt;/p&gt;
&lt;pre &gt;
$ (
  grep -v '^0[012]:' '#stackvm.08-28.log';
  cat '#stackvm.08-29.log';
  grep '^0[012]' '#stackvm.08-30.log'
  ) | wc -l
5069
&lt;/pre&gt;
&lt;p&gt;So 5069 events happened during the challenge. That's 105 events per hour on average. We have a special lulbot in it who tells us when we commit, for example:&lt;/p&gt;
&lt;pre &gt;
05:59 &amp;lt; lulzbot-X&gt; Whoa Nelly! New commits to pkrumins/node-chess (master)!
05:59 &amp;lt; lulzbot-X&gt;     * Peteris Krumins: MoveGenerator stub
05:59 &amp;lt; lulzbot-X&gt;     * Peteris Krumins: abstract pieces
05:59 &amp;lt; lulzbot-X&gt; githubs: http://github.com/pkrumins/node-chess/tree/master
&lt;/pre&gt;
&lt;p&gt;Here lulzbot informed us that I committed MoveGenerator stub and abstracted pieces in node-chess repo.&lt;/p&gt;
&lt;p&gt;Out of these 5069 events, we talked this much,&lt;/p&gt;
&lt;pre &gt;
$ (
  grep -v '^0[012]:' '#stackvm.08-28.log';
  cat '#stackvm.08-29.log';
  grep '^0[012]' '#stackvm.08-30.log'
  ) | egrep -i '^&amp;lt; pkrumins|substack|jesus' | wc -l
2682
&lt;/pre&gt;
&lt;p&gt;So we spoke 2682 times or 83.8 times per hour. We also asked quite a lot questions:&lt;/p&gt;
&lt;pre &gt;
$ (
  grep -v '^0[012]:' '#stackvm.08-28.log';
  cat '#stackvm.08-29.log';
  grep '^0[012]' '#stackvm.08-30.log';
  ) | grep '?$' | wc -l
246
&lt;/pre&gt;
&lt;p&gt;246 questions, for example (random selection):&lt;/p&gt;
&lt;pre &gt;
&amp;lt; pkrumins&gt; wait, are we including a version of socket.io.js in dnode?
&amp;lt; jesusabdullah&gt; but: simplified pieces for thumbs--yea or nay?
&amp;lt; pkrumins&gt; is anyone working ont he problem where the opponent cant make moves?
&amp;lt; SubStack&gt; pkrumins did you see how I just dumped the node EventEmitter code into our lib/?
&amp;lt; SubStack&gt; does S create a row?
&amp;lt; jesusabdullah&gt; pkrumins: You fixing the board?
&amp;lt; pkrumins&gt; how does resizing in raphael happen?
&lt;/pre&gt;
&lt;p&gt;My chess code wasn't the easiest to write and to make sure it works correctly, I wrote 52 &lt;a href="http://github.com/visionmedia/expresso"&gt;expresso&lt;/a&gt; tests,&lt;/p&gt;
&lt;pre &gt;
$ expresso 

   100% 52 tests
&lt;/pre&gt;
&lt;p&gt;Without tests I would have never got that chess code right.&lt;/p&gt;
&lt;p&gt;That's about it. The competition was awesome, A++ would participate again. Hope they organize node.js knockout the next year, too!&lt;/p&gt;
&lt;p&gt;I hope you enjoyed my post and don't forget to &lt;a href="http://nodeknockout.com/teams/dark-knights#your_vote"&gt;vote for our project&lt;/a&gt;! Your vote is so important to us. Thank you!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=7CGefS4mtHY:hf1WEiE1jDA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=7CGefS4mtHY:hf1WEiE1jDA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=7CGefS4mtHY:hf1WEiE1jDA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=7CGefS4mtHY:hf1WEiE1jDA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=7CGefS4mtHY:hf1WEiE1jDA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=7CGefS4mtHY:hf1WEiE1jDA:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=7CGefS4mtHY:hf1WEiE1jDA:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/7CGefS4mtHY" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/node-js-knockout-competition</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">StackVM Demo Video #2</title>
    <id>231</id>
    <updated>2010-08-10T10:20:30Z</updated>
    <published>2010-08-10T07:30:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/sc4EAbRvfxE/stackvm-demo-video-two" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dzizMT_0w-s_qjT5jZ2JBPLlPnc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dzizMT_0w-s_qjT5jZ2JBPLlPnc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dzizMT_0w-s_qjT5jZ2JBPLlPnc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dzizMT_0w-s_qjT5jZ2JBPLlPnc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="c"&gt;&lt;p&gt;&lt;a href="http://stackvm.com"&gt;&lt;img src="http://www.catonmat.net/images/stackvm.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Hey everyone. We at &lt;a href="http://stackvm.com"&gt;StackVM&lt;/a&gt; just finished recording the 2nd demo video. The 2nd video shows all the cool new features we have recently built - user login system, chatting and sharing of virtual machines by just dragging and dropping. Also this time &lt;a href="http://substack.net"&gt;James Halliday&lt;/a&gt; joins me from Fairbanks, Alaska!&lt;/p&gt;
&lt;p&gt;Here is the video #2,&lt;/p&gt;
&lt;div class="c"&gt;&lt;object width="576" height="467"&gt;&lt;param name="movie" value="http://www.youtube.com/v/ppXUbj0MA3E&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1"&gt;&lt;/param&gt;
&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;
&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;
&lt;embed src="http://www.youtube.com/v/ppXUbj0MA3E&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="576" height="467"&gt;&lt;/embed&gt;
&lt;/object&gt;
&lt;p&gt;&lt;small&gt;StackVM brings virtual machines to the web. Join #stackvm on FreeNode to discuss!&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you haven't seen the first video, see my &lt;a href="http://www.catonmat.net/blog/i-am-doing-a-startup"&gt;StackVM startup announcement post&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Also, if you wish to be the first to try StackVM when we launch, please leave your email below. We'll send you a free demo as soon as we can!&lt;/p&gt;
&lt;div class="c"&gt;&lt;div class="stackvm-form"&gt;&lt;form action="http://stackvm.com/sign-up.cgi" method="POST"&gt;&lt;p&gt;   &lt;input type="hidden" name="from" value="catonmat"&gt;&lt;br&gt;
   &lt;input type="hidden" name="back" value="http://www.catonmat.net/blog/stackvm-demo-video-two"&gt;&lt;br&gt;
   Your email: &lt;input type="text" name="email"&gt; &lt;input type="submit" value="Submit"&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;During the past few weeks we have also written two new node.js libraries for use at StackVM:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-gif"&gt;node-gif&lt;/a&gt; - for producing GIF images and animated GIFs (gifcasts).&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-image"&gt;node-image&lt;/a&gt; - unifies &lt;a href="http://github.com/pkrumins/node-png"&gt;node-png&lt;/a&gt;, &lt;a href="http://github.com/pkrumins/node-gif"&gt;node-gif&lt;/a&gt; and &lt;a href="http://github.com/pkrumins/node-jpeg"&gt;node-jpeg&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We did not demo gifcasts in this video but I am going to do a separate video in the next week or two showing just that. They're pretty awesome!&lt;/p&gt;
&lt;p&gt;In a few weeks we'll also post the 3rd demo video. In that video we have planned to show virtual network editor that allows to network virtual machines by just dragging and dropping! Be sure to subscribe to &lt;a href="http://www.catonmat.net/feed/"&gt;catonmat's rss feed&lt;/a&gt; and &lt;a href="http://twitter.com/pkrumins"&gt;follow me on twitter&lt;/a&gt; to know when the video is out!&lt;/p&gt;
&lt;p&gt;See you!&lt;/p&gt;
&lt;p&gt;Ps. Join #stackvm on FreeNode to discuss StackVM with me and James! We're there 24/7!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sc4EAbRvfxE:4o36azLA1Xo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sc4EAbRvfxE:4o36azLA1Xo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=sc4EAbRvfxE:4o36azLA1Xo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sc4EAbRvfxE:4o36azLA1Xo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=sc4EAbRvfxE:4o36azLA1Xo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sc4EAbRvfxE:4o36azLA1Xo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=sc4EAbRvfxE:4o36azLA1Xo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/sc4EAbRvfxE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/stackvm-demo-video-two</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Announcement: I am doing a startup - StackVM!</title>
    <id>226</id>
    <updated>2010-08-10T10:21:12Z</updated>
    <published>2010-07-21T12:10:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/Xx1yGj-DeVo/i-am-doing-a-startup" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RzRUAOkPPH453s32hYvs-HDP0po/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RzRUAOkPPH453s32hYvs-HDP0po/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RzRUAOkPPH453s32hYvs-HDP0po/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RzRUAOkPPH453s32hYvs-HDP0po/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Hey everyone,&lt;/p&gt;
&lt;p&gt;I have exceptional news - I am doing a startup together with &lt;a href="http://substack.net"&gt;James Halliday&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I met James on FreeNode several years ago and it turned out that we had very similar ideas about doing great hacking. So we teamed up as equal co-founders to do a startup. We're on different continents but we use IRC, &lt;a href="http://github.com/pkrumins/stackvm"&gt;GitHub&lt;/a&gt; and &lt;a href="http://www.wedoist.com"&gt;WeDoist&lt;/a&gt; to get stuff done!&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;a href="http://stackvm.com"&gt;&lt;img src="http://www.catonmat.net/images/stackvm.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Check out an early demo of our software:&lt;/p&gt;
&lt;div class="c"&gt;&lt;object width="576" height="447"&gt;&lt;param name="movie" value="http://www.youtube.com/v/TWdkNO6XlFI&amp;amp;hl=en_US&amp;amp;fs=1"&gt;&lt;/param&gt;
&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;
&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;
&lt;embed src="http://www.youtube.com/v/TWdkNO6XlFI&amp;amp;hl=en_US&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="576" height="447"&gt;&lt;/embed&gt;
&lt;/object&gt;
&lt;p&gt;&lt;small&gt;StackVM brings virtual machines to the web. Join #stackvm on FreeNode to discuss!&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We can't present a live demo of our startup right now because we don't have that much computing power, however we'll soon be able to send out time-limited demos to several people a day. If you wish to try our software before anyone else does, fill in this form and we'll send you an invite code as soon as we have the hardware:&lt;/p&gt;
&lt;div class="c"&gt;&lt;div class="stackvm-form"&gt;&lt;form action="http://stackvm.com/sign-up.cgi" method="POST"&gt;&lt;p&gt;   &lt;input type="hidden" name="from" value="catonmat"&gt;&lt;br&gt;
   &lt;input type="hidden" name="back" value="http://www.catonmat.net/blog/i-am-doing-a-startup"&gt;&lt;br&gt;
   Your email: &lt;input type="text" name="email"&gt; &lt;input type="submit" value="Submit"&gt;&lt;br&gt;
  &lt;/p&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The startup we're doing is called &lt;strong&gt;&lt;a href="http://www.stackvm.com"&gt;StackVM&lt;/a&gt;&lt;/strong&gt;. StackVM makes virtual machines much more accessible over the web, makes them easier to use, and makes them embeddable in webpages (like putting a virtual machine in a blog post). This is just the first step that we're starting with. Next we're making networking between them very easy, just drag and drop to create any virtual network topology you wish, with firewalls, switches, etc. (fun for hacking competitions and learning networking). Then we're making what we call "vmcasts" - much like a screencasts, except the computation is recorded, meaning that at any point you can break into the playing vmcast and change the course of computation (and return back to it later).&lt;/p&gt;
&lt;p&gt;Our plan is to host the virtual machines and our awesome software for you, so that you don't have to worry about anything. We'll make sure it all works! At the moment we're actually already at our third major iteration of the software.&lt;/p&gt;
&lt;p&gt;Here are a few use cases:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;Suppose you're selling software and you want your users to try it before they buy it. Perfect use of StackVM - put your software in the virtual machine and embed it on your products page. The potential customers can try your software before they buy it right from your website!&lt;/li&gt;
 &lt;li&gt;Suppose you're an application developer and have written a program that should work cross-platform. You can easily rent 10 virtual machines with Linux, Windows, MacOS, and other operating systems and test your software. Just drag and drop it into the virtual machines, and you can test your software!&lt;/li&gt;
 &lt;li&gt;Suppose you want to teach someone how to work in Perl in a series of blog posts (like I do), you can embed the terminal with a vmcast in your blog post, and everyone can follow your tutorial, and also try out the examples interactively, in a real shell!&lt;/li&gt;
 &lt;li&gt;You can build a virtual honeypot network and have hackers break into it, then analyse how they did breakins. Or, you can build a huge network and learn routing and networking concepts!&lt;/li&gt;
 &lt;li&gt;Suppose you want to share your work with a group of people. You can easily do it in stackvm! Just send the other people link to your VM and they can connect to it with any web browser. They'll be able to see what you're doing, comment on your work, and if you allow fix your bugs (think pair programming!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hosting virtual machines requires a lot of infrastructure, so we plan to start collecting revenue as soon as possible with affordable paid user accounts. We're not going to do the common nonsense among startups of first building up the project for years and only then trying to figure out how to make it profitable. We're going to offer virtual machines together with an awesome interface and features to them as a monthly paid service from the day we launch. We're also going to have an open API to our software, so that you can build on top of it or customize it (for example script virtual machines to do something specific).&lt;/p&gt;
&lt;p&gt;We're also testing out the idea of complete openness with this startup. It's going to be 100% open-source and 100% idea-open, meaning that anyone can read what we're up to, and run our code if they want to run stackvm on their own. So far we have shared all the code on github (&lt;a href="http://github.com/pkrumins/stackvm"&gt;my stackvm repo&lt;/a&gt;, &lt;a href="http://github.com/substack/stackvm"&gt;James's stackvm repo&lt;/a&gt;) and documented most of the ideas and experiments on &lt;a href="http://wiki.github.com/substack/stackvm/"&gt;stackvm github wiki&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;We're applying for YC funding later this year so that we can focus on hacking and not paperwork.&lt;/p&gt;
&lt;p&gt;Now a little bit about the tech we use at StackVM. I won't go into much details right now because many of the future posts will detail the tech at StackVM.&lt;/p&gt;
&lt;p&gt;At the moment StackVM is in its 3rd major iteration already and is almost entirely built on &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt;. Since we're doing everything open-source, we've written a bunch of reusable node.js modules:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="http://github.com/substack/dnode"&gt;dnode&lt;/a&gt; - Simple asynchronous remote method invocation for node.js.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/substack/node-bufferlist"&gt;node-bufferlist&lt;/a&gt; - Abstraction of node.js's buffers and monadic binary parsing.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/substack/node-rfb"&gt;node-rfb&lt;/a&gt; - Implements the client-side of the RFB protocol that VNC uses.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-png"&gt;node-png&lt;/a&gt; - Produces PNG images from RGB or RGBA values.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-jpeg"&gt;node-jpeg&lt;/a&gt; - Produces JPEG images from RGB or RGBA values.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-video"&gt;node-video&lt;/a&gt; - Records Theora/Ogg videos from RGB values.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-base64"&gt;node-base64&lt;/a&gt; - Encodes binary data to base64 to send across websockets and ajax.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-jsmin"&gt;node-jsmin&lt;/a&gt; - Minify JavaScript on the server side, before sending it to the browser.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://github.com/pkrumins/node-bufferdiff"&gt;node-bufferdiff&lt;/a&gt; - A module to compare two buffers quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'll keep everyone updated on the progress and technical insight into our development. If you're not yet subscribed to my posts, please do it - &lt;a href="http://www.catonmat.net/feed"&gt;catonmat rss feed&lt;/a&gt;. Going to make this happen!&lt;/p&gt;
&lt;p&gt;And if you wish to talk about our software, come join #stackvm on FreeNode!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Xx1yGj-DeVo:edKzBdHvZ4E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Xx1yGj-DeVo:edKzBdHvZ4E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=Xx1yGj-DeVo:edKzBdHvZ4E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Xx1yGj-DeVo:edKzBdHvZ4E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=Xx1yGj-DeVo:edKzBdHvZ4E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=Xx1yGj-DeVo:edKzBdHvZ4E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=Xx1yGj-DeVo:edKzBdHvZ4E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/Xx1yGj-DeVo" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/i-am-doing-a-startup</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Three Years of Blogging</title>
    <id>225</id>
    <updated>2010-07-08T16:09:03Z</updated>
    <published>2010-07-06T17:02:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/LD7qo8re6-c/three-years-of-blogging" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/i3W-bp_-Qx-idxkXze3Ega5xQ-Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/i3W-bp_-Qx-idxkXze3Ega5xQ-Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/i3W-bp_-Qx-idxkXze3Ega5xQ-Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/i3W-bp_-Qx-idxkXze3Ega5xQ-Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2009/07/two-years-of-blogging.jpg' alt='A Year of Blogging' class="post-icon" align="left"&gt;Hey everyone! Another year has passed and it's now 3 years since I've been blogging here on catonmat! In this post I wish to summarize this year's statistics.&lt;/p&gt;
&lt;p&gt;See the &lt;a href="http://www.catonmat.net/blog/a-year-of-blogging/"&gt;one year of blogging&lt;/a&gt; and &lt;a href="http://www.catonmat.net/blog/two-years-of-blogging"&gt;two years of blogging&lt;/a&gt; for previous year statistics.&lt;/p&gt;
&lt;p&gt;First of all traffic statistics,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;a href="http://www.catonmat.net/images/third-year-of-blogging/catonmat-visitor-statistics-3rd-year-full.jpg"&gt;&lt;img src="http://www.catonmat.net/images/third-year-of-blogging/catonmat-visitor-statistics-3rd-year.jpg"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;Traffic statistics for the period 2009-07-01 - 2010-07-01 from Google Analytics.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Alright, so catonmat has received 1.43 million visitors and 2.11 million page views during this year. That's 120k visits and 175k page views per month. Or 4,000 visitors per day and 5,800 page views per day. Good numbers.&lt;/p&gt;
&lt;p&gt;Let's look at the whole traffic picture from the day one of blogging,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;a href="http://www.catonmat.net/images/third-year-of-blogging/catonmat-visitor-statistics-all-years-full.jpg"&gt;&lt;img src="http://www.catonmat.net/images/third-year-of-blogging/catonmat-visitor-statistics-all-years.jpg"&gt;&lt;/a&gt;&lt;br&gt;
&lt;small&gt;Traffic statistics for the period 2007-07-01 - 2010-07-01 from Google Analytics.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Looks pretty random but seems to have a hidden linear trend upwards.&lt;/p&gt;
&lt;p&gt;Now the FeedBurner subscriber stats,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/third-year-of-blogging/catonmat-feedburner-statistics-3rd-year.png"&gt;&lt;br&gt;
&lt;small&gt;Feedburner statistics for the period 2009-07-01 - 2010-07-01.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Last year I left off with 7000 subscribers, and now I have around 12,000. That's 5000 new subscribers, or 13 new subscribers per day on average.&lt;/p&gt;
&lt;p&gt;And the whole picture of subscriber dynamics since the beginning of blogging,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/third-year-of-blogging/catonmat-feedburner-statistics-all-years.png"&gt;&lt;br&gt;
&lt;small&gt;Feedburner statistics for the period 2007-07-01 - 2010-07-01.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Also a nice positive trend, if it keeps going the same way, I expect to have around 17,000 subscribers the next year.&lt;/p&gt;
&lt;p&gt;Now to articles. During this year I have written 43 articles. Here are ten most popular ones:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="/blog/using-fibonacci-numbers-to-convert-from-miles-to-kilometers"&gt;Using Fibonacci Numbers to Convert from Miles to Kilometers and Vice Versa&lt;/a&gt; (194,417 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/top-ten-one-liners-from-commandlinefu-explained"&gt;Top Ten One-Liners from CommandLineFu Explained&lt;/a&gt;  (155,079 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/unix-utilities-lsof"&gt;A Unix Utility You Should Know About: lsof&lt;/a&gt; (59,204 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/ldd-arbitrary-code-execution"&gt;ldd arbitrary code execution&lt;/a&gt; (55,833 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/summary-of-mit-introduction-to-algorithms"&gt;Summary of all the MIT Introduction to Algorithms lectures&lt;/a&gt; (54,954 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/must-have-windows-programs"&gt;Must-Have Windows Software (or Windows Programs that I use)&lt;/a&gt; (53,825 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/busy-beaver"&gt;The Busy Beaver Problem&lt;/a&gt; (52,238 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/vim-plugins-snipmate-vim"&gt;Vim Plugins You Should Know About, Part IV: snipmate.vim&lt;/a&gt; (35,735 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/secret-perl-operators"&gt;Secret Perl Operators&lt;/a&gt; (34,346 views).&lt;/li&gt;
 &lt;li&gt;&lt;a href="/http-proxy-in-nodejs"&gt;A HTTP Proxy Server in 20 Lines of node.js Code&lt;/a&gt; (31,822 views).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are my personal favorites that didn't make it into top ten:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="/blog/on-the-linear-time-algorithm-for-finding-fibonacci-numbers"&gt;On the Linear Time Algorithm For Finding Fibonacci Numbers&lt;/a&gt;.&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/recursive-regular-expressions"&gt;Recursive Regular Expressions&lt;/a&gt;.&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/on-functors"&gt;On Functors&lt;/a&gt;.&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/derivation-of-ycombinator"&gt;Deriving the Y-Combinator&lt;/a&gt;.&lt;/li&gt;
 &lt;li&gt;&lt;a href="/blog/donald-knuths-first-computer"&gt;Donald Knuth's First Computer&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's now time for delicious cake:&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/images/third-year-of-blogging/portal-cake-three-years.jpg"&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Let's meet for cake the next year again! See you!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=LD7qo8re6-c:VRUMM9NZ5tg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=LD7qo8re6-c:VRUMM9NZ5tg:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=LD7qo8re6-c:VRUMM9NZ5tg:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=LD7qo8re6-c:VRUMM9NZ5tg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=LD7qo8re6-c:VRUMM9NZ5tg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=LD7qo8re6-c:VRUMM9NZ5tg:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=LD7qo8re6-c:VRUMM9NZ5tg:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/LD7qo8re6-c" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/three-years-of-blogging</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">The Four Polymorphisms in C++</title>
    <id>224</id>
    <updated>2010-06-20T05:20:52Z</updated>
    <published>2010-06-18T10:10:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/hw0jXfDKemQ/cpp-polymorphism" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zdTcKcj8EaKYC_WVPtwawRlkAik/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zdTcKcj8EaKYC_WVPtwawRlkAik/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zdTcKcj8EaKYC_WVPtwawRlkAik/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zdTcKcj8EaKYC_WVPtwawRlkAik/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;When people talk about polymorphism in C++ they usually mean the thing of using a derived class through the base class pointer or reference, which is called &lt;strong&gt;subtype polymorphism&lt;/strong&gt;. But they often forget that there are all kinds of other polymorphisms in C++, such as &lt;strong&gt;parametric polymorphism&lt;/strong&gt;, &lt;strong&gt;ad-hoc polymorphism&lt;/strong&gt; and &lt;strong&gt;coercion polymorphism&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;These polymorphisms also go by different names in C++,&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;Subtype polymorphism is also known as &lt;strong&gt;runtime polymorphism&lt;/strong&gt;.&lt;/li&gt;
 &lt;li&gt;Parametric polymorphism is also known as &lt;strong&gt;compile-time polymorphism&lt;/strong&gt;.&lt;/li&gt;
 &lt;li&gt;Ad-hoc polymorphism is also known as &lt;strong&gt;overloading&lt;/strong&gt;.&lt;/li&gt;
 &lt;li&gt;Coercion is also known as (implicit or explicit) &lt;strong&gt;casting&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this article I'll illustrate all the polymorphisms through examples in C++ language and also give insight on why they have various other names.&lt;/p&gt;
&lt;h2&gt;Subtype Polymorphism (Runtime Polymorphism)&lt;/h2&gt;
&lt;p&gt;Subtype polymorphism is what everyone understands when they say "polymorphism" in C++. It's the ability to use derived classes through base class pointers and references.&lt;/p&gt;
&lt;p&gt;Here is an example. Suppose you have various cats like these felines,&lt;/p&gt;
&lt;div class="c"&gt;&lt;p&gt;&lt;img src="/images/polymorphic-cats.gif" alt="Polymorphic Cats"&gt;&lt;br&gt;
&lt;small&gt;Polymorphic cats on a mat by &lt;a href="http://substack.net"&gt;James Halliday&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Since they are all of Felidae biological family, and they all should be able to meow, they can be represented as classes inheriting from &lt;code&gt;Felid&lt;/code&gt; base class and overriding the &lt;code&gt;meow&lt;/code&gt; pure virtual function,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="c1"&gt;// file cats.h&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Felid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;meow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Felid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;meow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Meowing like a regular cat! meow!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tiger&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Felid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;meow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Meowing like a tiger! MREOWWW!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ocelot&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Felid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;meow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Meowing like an ocelot! mews!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now the main program can use &lt;code&gt;Cat&lt;/code&gt;, &lt;code&gt;Tiger&lt;/code&gt; and &lt;code&gt;Ocelot&lt;/code&gt; interchangeably through &lt;code&gt;Felid&lt;/code&gt; (base class) pointer,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include &amp;quot;cats.h&amp;quot;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;do_meowing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Felid&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;meow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;Cat&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="n"&gt;Tiger&lt;/span&gt; &lt;span class="n"&gt;tiger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="n"&gt;Ocelot&lt;/span&gt; &lt;span class="n"&gt;ocelot&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="n"&gt;do_meowing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="n"&gt;do_meowing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tiger&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="n"&gt;do_meowing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ocelot&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here the main program passes pointers to &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;tiger&lt;/code&gt; and &lt;code&gt;ocelot&lt;/code&gt; to &lt;code&gt;do_meowing&lt;/code&gt; function that expects a pointer to &lt;code&gt;Felid&lt;/code&gt;. Since they are all &lt;code&gt;Felid&lt;/code&gt;s, the program calls the right &lt;code&gt;meow&lt;/code&gt; function for each felid and the output is:&lt;/p&gt;
&lt;pre &gt;
Meowing like a regular cat! meow!
Meowing like a tiger! MREOWWW!
Meowing like an ocelot! mews!
&lt;/pre&gt;
&lt;p&gt;Subtype polymorphism is also called &lt;strong&gt;runtime polymorphism&lt;/strong&gt; for a good reason. The resolution of polymorphic function calls happens at runtime through an indirection via the virtual table. Another way of explaining this is that compiler does not locate the address of the function to be called at compile-time, instead when the program is run, the function is called by dereferencing the right pointer in the virtual table.&lt;/p&gt;
&lt;p&gt;In type theory it's also known as &lt;strong&gt;inclusion polymorphism&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Parametric Polymorphism (Compile-Time Polymorphism)&lt;/h2&gt;
&lt;p&gt;Parametric polymorphism provides a means to execute the same code for any type. In C++ parametric polymorphism is implemented via templates.&lt;/p&gt;
&lt;p&gt;One of the simplest examples is a generic &lt;code&gt;max&lt;/code&gt; function that finds maximum of two of its arguments,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// 9&lt;/span&gt;

 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;quot;foo&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here the &lt;code&gt;max&lt;/code&gt; function is polymorphic on type &lt;code&gt;T&lt;/code&gt;. Note, however, that it doesn't work on pointer types because comparing pointers compares the memory locations and not the contents. To get it working for pointers you'd have to specialize the template for pointer types and that would no longer be parametric polymorphism but would be ad-hoc polymorphism.&lt;/p&gt;
&lt;p&gt;Since parametric polymorphism happens at compile time, it's also called &lt;strong&gt;compile-time polymorphism&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Ad-hoc Polymorphism (Overloading)&lt;/h2&gt;
&lt;p&gt;Ad-hoc polymorphism allows functions with the same name act differently for each type. For example, given two &lt;code&gt;int&lt;/code&gt;s and the &lt;code&gt;+&lt;/code&gt; operator, it adds them together. Given two &lt;code&gt;std::string&lt;/code&gt;s it concatenates them together. This is called &lt;strong&gt;overloading&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Here is a concrete example that implements function &lt;code&gt;add&lt;/code&gt; for &lt;code&gt;int&lt;/code&gt;s and &lt;code&gt;string&lt;/code&gt;s,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hello &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;world&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ad-hoc polymorphism also appears in C++ if you specialize templates. Returning to the previous example about &lt;code&gt;max&lt;/code&gt; function, here is how you'd write a max for two &lt;code&gt;char *&lt;/code&gt;,&lt;/p&gt;
&lt;pre &gt;
template &amp;lt;&gt;
const char *max(const char *a, const char *b) {
 return strcmp(a, b) &gt; 0 ? a : b;
}
&lt;/pre&gt;
&lt;p&gt;Now you can call &lt;code&gt;::max("foo", "bar")&lt;/code&gt; to find maximum of strings "foo" and "bar".&lt;/p&gt;
&lt;h2&gt;Coercion Polymorphism (Casting)&lt;/h2&gt;
&lt;p&gt;Coercion happens when an object or a primitive is cast into another object type or primitive type. For example,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// int gets promoted (cast) to float implicitly&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;9.99&lt;/span&gt; &lt;span class="c1"&gt;// float gets demoted to int implicitly&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Explicit casting happens when you use C's type-casting expressions, such as &lt;code&gt;(unsigned int *)&lt;/code&gt; or &lt;code&gt;(int)&lt;/code&gt; or C++'s &lt;code&gt;static_cast&lt;/code&gt;, &lt;code&gt;const_cast&lt;/code&gt;, &lt;code&gt;reinterpret_cast&lt;/code&gt;, or &lt;code&gt;dynamic_cast&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Coercion also happens if the constructor of a class isn't &lt;code&gt;explicit&lt;/code&gt;, for example,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ffoo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ffoo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
 &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;giggidy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;moo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;giggidy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;moo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// prints 55&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you made the constructor of A &lt;code&gt;explicit&lt;/code&gt;, that would no longer be possible. It's always a good idea to make your constructors explicit to avoid accidental conversions.&lt;/p&gt;
&lt;p&gt;Also if a class defines conversion operator for type &lt;code&gt;T&lt;/code&gt;, then it can be used anywhere where type &lt;code&gt;T&lt;/code&gt; is expected.&lt;/p&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CrazyInt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
 &lt;span class="n"&gt;CrazyInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
 &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// conversion from CrazyInt to int&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;CrazyInt&lt;/code&gt; defines a conversion operator to type &lt;code&gt;int&lt;/code&gt;. Now if we had a function, let's say, &lt;code&gt;print_int&lt;/code&gt; that took &lt;code&gt;int&lt;/code&gt; as an argument, we could also pass it an object of type CrazyInt,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;print_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;CrazyInt&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="n"&gt;print_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// prints 999&lt;/span&gt;
 &lt;span class="n"&gt;print_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// prints 55&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Subtype polymorphism that I discussed earlier is actually also coercion polymorphism because the derived class gets converted into base class type.&lt;/p&gt;
&lt;h2&gt;Have Fun!&lt;/h2&gt;
&lt;p&gt;Have fun with all the new knowledge about polymorphism!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=hw0jXfDKemQ:Ytq4OVbydhY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=hw0jXfDKemQ:Ytq4OVbydhY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=hw0jXfDKemQ:Ytq4OVbydhY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=hw0jXfDKemQ:Ytq4OVbydhY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=hw0jXfDKemQ:Ytq4OVbydhY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=hw0jXfDKemQ:Ytq4OVbydhY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=hw0jXfDKemQ:Ytq4OVbydhY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/hw0jXfDKemQ" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/cpp-polymorphism</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Yet Another Ten One-Liners from CommandLineFu Explained</title>
    <id>222</id>
    <updated>2010-06-09T20:10:01Z</updated>
    <published>2010-06-02T12:45:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/dqjNsh7dF8k/yet-another-ten-one-liners-from-commandlinefu-explained" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/63fE5Cv6sgPuz2HNtgxled60Iv8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/63fE5Cv6sgPuz2HNtgxled60Iv8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/63fE5Cv6sgPuz2HNtgxled60Iv8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/63fE5Cv6sgPuz2HNtgxled60Iv8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/blog/wp-content/uploads/2010/03/commandlinefu-explained.jpg" alt="CommandLineFu Explained" class="post-icon" align="left"&gt;Hey everyone, this is the fourth article in the series on the most popular &lt;a href="http://www.commandlinefu.com/"&gt;commandlinefu&lt;/a&gt; one-liners explained.&lt;/p&gt;
&lt;p&gt;Here are the first three parts:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained/"&gt;Part I: Top Ten One-Liners from CommandLineFu Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/the-next-ten-one-liners-from-commandlinefu-explained/"&gt;Part II: The Next Ten One-Liners from CommandLineFu Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/another-ten-one-liners-from-commandlinefu-explained/"&gt;Part III: Another Ten One-Liners from CommandLineFu Explained&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And here are today's one-liners:&lt;/p&gt;
&lt;h2&gt;31. Quickly access ASCII table.&lt;/h2&gt;
&lt;pre &gt;$ man 7 ascii&lt;/pre&gt;
&lt;p&gt;Ever forgot a keycode for some ASCII character or escape code? Look no further, &lt;code&gt;man ascii&lt;/code&gt; contains the 7-bit ASCII table. Take a look at it &lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/ascii.7.html"&gt;online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Linux &lt;a href="http://www.kernel.org/doc/man-pages/"&gt;man pages&lt;/a&gt; are full of gems like these. One day I actually went through all the man pages to find the most interesting ones. An article about them is upcoming but before I get it published, here are a few interesting ones:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man1/intro.1.html"&gt;man 1 intro&lt;/a&gt; - a tutorial that gets you started with Linux if you have never used it.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man2/syscalls.2.html"&gt;man 2 syscalls&lt;/a&gt; - lists all Linux system calls by kernel version.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man2/select_tut.2.html"&gt;man 2 select_tut&lt;/a&gt; - &lt;code&gt;select()&lt;/code&gt; system call tutorial.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man3/string.3.html"&gt;man 3 string&lt;/a&gt; - lists all &amp;lt;string.h&amp;gt; string manipulation functions.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man3/stdio.3.html"&gt;man 3 stdio&lt;/a&gt; - lists and describes all &amp;lt;stdio.h&amp;gt; standard input/output library functions.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man3/errno.3.html"&gt;man 3 errno&lt;/a&gt; - lists and describes all &lt;code&gt;errno&lt;/code&gt; error numbers.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man4/console_codes.4.html"&gt;man 4 console_codes&lt;/a&gt; - Linux console escape and control sequences.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man4/full.4.html"&gt;man 4 full&lt;/a&gt; - &lt;code&gt;/dev/full&lt;/code&gt; - a device that simulates a full device.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html"&gt;man 5 proc&lt;/a&gt; - lots of info about the &lt;code&gt;/proc&lt;/code&gt; filesystem.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man5/filesystems.5.html"&gt;man 5 filesystems&lt;/a&gt; - lists various Linux filesystems.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And finally the section 7 man pages that are most packed with wild and cool info,&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/bootparam.7.html"&gt;man 7 bootparam&lt;/a&gt; - a tutorial and reference of Linux kernel boot parameters.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/charsets.7.html"&gt;man 7 charsets&lt;/a&gt; - a Linux programmer's view of character sets and internationalization.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/glob.7.html"&gt;man 7 glob&lt;/a&gt; - how pathname globbing works.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/hier.7.html"&gt;man 7 hier&lt;/a&gt; - description of the Linux file system hierarchy.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/operator.7.html"&gt;man 7 operator&lt;/a&gt; - C language operator precedence and associativity table.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/regex.7.html"&gt;man 7 regex&lt;/a&gt; - basic and extended regular expression overview.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/suffixes.7.html"&gt;man 7 suffixes&lt;/a&gt; - lists common Linux file suffixes and the associated file types.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/time.7.html"&gt;man 7 time&lt;/a&gt; - overview of time and timers.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/units.7.html"&gt;man 7 units&lt;/a&gt; - kilo, kibi, mega, mebi, giga, gibi, ... - decimal (SI) and binary system of units.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/utf8.7.html"&gt;man 7 utf8&lt;/a&gt; - description of UTF-8 encoding.&lt;/li&gt;
 &lt;li&gt;&lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/url.7.html"&gt;man 7 url&lt;/a&gt; - description of URIs, URLs and URNs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are a lot more interesting man pages but these stood out from the rest.&lt;/p&gt;
&lt;h2&gt;32. Simple timer.&lt;/h2&gt;
&lt;pre &gt;$ time read&lt;/pre&gt;
&lt;p&gt;This one-liner can be used a simple timer. For example, if you wish to time something, you can execute it when the event starts and press the return key when the event ends. It will output the time the event took to finish.&lt;/p&gt;
&lt;p&gt;Here is how this one-liner works. First the &lt;code&gt;time&lt;/code&gt; command times any command that is supplied to it. In this case the command supplied to it is &lt;code&gt;read&lt;/code&gt; that reads a line from the standard input. As soon as you press enter, &lt;code&gt;read&lt;/code&gt; finishes and time reports how long it took.&lt;/p&gt;
&lt;p&gt;If you get annoyed by having to press enter, you can specify that &lt;code&gt;read&lt;/code&gt; should return after having read 1 character,&lt;/p&gt;
&lt;pre &gt;$ time read -N 1&lt;/pre&gt;
&lt;p&gt;Now you can press any key to stop the timer.&lt;/p&gt;
&lt;p&gt;If you wish to run a timer for a specific number of seconds, you can add &lt;code&gt;-t&lt;/code&gt; flag for timeout,&lt;/p&gt;
&lt;pre &gt;$ time read -t 60&lt;/pre&gt;
&lt;p&gt;This would stop the timer after 60 seconds.&lt;/p&gt;
&lt;h2&gt;33. Shutdown a Windows machine.&lt;/h2&gt;
&lt;pre &gt;$ net rpc shutdown -I IP_ADDRESS -U username%password&lt;/pre&gt;
&lt;p&gt;Everyone knows the &lt;code&gt;net&lt;/code&gt; command, right? We all used to &lt;code&gt;net use \\ip\ipc$ *&lt;/code&gt;, right? :)&lt;/p&gt;
&lt;p&gt;Anyway, the &lt;code&gt;net&lt;/code&gt; command comes as part of &lt;a href="http://samba.org/"&gt;Samba&lt;/a&gt;, which allows you, for example, to use Linux in a Windows workgroup.&lt;/p&gt;
&lt;p&gt;This particular one-liner executes the &lt;code&gt;shutdown&lt;/code&gt; command on a Windows computer located at &lt;code&gt;IP_ADDRESS&lt;/code&gt; with as the user &lt;code&gt;username&lt;/code&gt; with password &lt;code&gt;password&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To reboot a machine use the &lt;code&gt;-r&lt;/code&gt; switch to &lt;code&gt;net rpc&lt;/code&gt;:&lt;/p&gt;
&lt;pre &gt;$ net rpc shutdown -r -I IP_ADDRESS -U username%password&lt;/pre&gt;
&lt;p&gt;If you're on an unsecured network, don't forget about the good old &lt;code&gt;nmblookup&lt;/code&gt; and &lt;code&gt;smbclient&lt;/code&gt; tools that come with Samba.&lt;/p&gt;
&lt;h2&gt;34. Execute a command independently from the current shell.&lt;/h2&gt;
&lt;pre &gt;$ (cd /tmp &amp;&amp; ls)&lt;/pre&gt;
&lt;p&gt;This one-liner illustrates subshells. Here the commands &lt;code&gt;cd /tmp&lt;/code&gt; and &lt;code&gt;ls&lt;/code&gt; are executed but they do not affect the current shell. If you had done just &lt;code&gt;cd /tmp &amp;&amp; ls&lt;/code&gt;, your current shell would have changed directory to &lt;code&gt;/tmp&lt;/code&gt; but in this one-liner it happens in a subshell and your current shell is not affected.&lt;/p&gt;
&lt;p&gt;Surely, this is only a toy example. If you wanted to know what's in &lt;code&gt;/tmp&lt;/code&gt;, you'd do just &lt;code&gt;ls /tmp&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Actually, talking about &lt;code&gt;cd&lt;/code&gt;, be aware of &lt;code&gt;pushd&lt;/code&gt; and &lt;code&gt;popd&lt;/code&gt; commands. They allow you to maintain a stack of directories you want to return to later. For example,&lt;/p&gt;
&lt;pre &gt;
/long/path/is/long$ pushd .
/long/path/is/long$ cd /usr
/usr$ popd 
/long/path/is/long$
&lt;/pre&gt;
&lt;p&gt;Or even shorter, passing the directory you're gonna &lt;code&gt;cd&lt;/code&gt; to directly to &lt;code&gt;pushd&lt;/code&gt;,&lt;/p&gt;
&lt;pre &gt;
/long/path/is/long$ pushd /usr
/usr$ popd 
/long/path/is/long$
&lt;/pre&gt;
&lt;p&gt;Another cool trick is to use &lt;code&gt;cd -&lt;/code&gt; to return to the previous directory. Here is an example,&lt;/p&gt;
&lt;pre &gt;
/home/pkrumins$ cd /tmp
/tmp$ cd -
/home/pkrumins$
&lt;/pre&gt;
&lt;h2&gt;35. Tunnel your SSH connection via intermediate host.&lt;/h2&gt;
&lt;pre &gt;$ ssh -t reachable_host ssh unreachable_host&lt;/pre&gt;
&lt;p&gt;This one-liner creates an ssh connection to &lt;code&gt;unreachable_host&lt;/code&gt; via &lt;code&gt;reachable_host&lt;/code&gt;. It does it by executing the &lt;code&gt;ssh unreachable_host&lt;/code&gt; on &lt;code&gt;reachable_host&lt;/code&gt;. The &lt;code&gt;-t&lt;/code&gt; forces ssh to allocate a pseudo-tty, which is necessary for working interactively in the second ssh to &lt;code&gt;unreachable_host&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This one-liner can be generalized. You can tunnel through arbitrary number of ssh servers:&lt;/p&gt;
&lt;pre &gt;$ ssh -t host1 ssh -t host2 ssh -t host3 ssh -t host4 ...&lt;/pre&gt;
&lt;p&gt;Now catch me if you can. ;)&lt;/p&gt;
&lt;h2&gt;36. Clear the terminal screen.&lt;/h2&gt;
&lt;pre &gt;$ CTRL+l&lt;/pre&gt;
&lt;p&gt;Pressing CTRL+l (that's small &lt;code&gt;L&lt;/code&gt;) clears the screen leaving the current line at the top of the screen.&lt;/p&gt;
&lt;p&gt;If you wish to clear just some line, you can use argumented version of &lt;code&gt;CTRL+l&lt;/code&gt; - first press &lt;code&gt;ESC&lt;/code&gt;, then the line you want to clear, let's say 21 (21st line), and then press the same CTRL+l. That will clear the 21st line on the screen without erasing the whole screen.&lt;/p&gt;
&lt;pre &gt;$ ESC 21 CTRL+l&lt;/pre&gt;
&lt;p&gt;This command outputs a special "clear-screen" sequence to the terminal. The same can be achieved by &lt;code&gt;tput&lt;/code&gt; command,&lt;/p&gt;
&lt;pre &gt;$ tput clear&lt;/pre&gt;
&lt;p&gt;Another way to clear the terminal (usually when the screen gets garbled) is to use the &lt;code&gt;reset&lt;/code&gt; command,&lt;/p&gt;
&lt;pre &gt;$ reset&lt;/pre&gt;
&lt;h2&gt;37. Hear when the machine comes back online.&lt;/h2&gt;
&lt;pre &gt;$ ping -a IP&lt;/pre&gt;
&lt;p&gt;Ever had a situation when you need to know when the system comes up after a reboot? Up until now you probably launched &lt;code&gt;ping&lt;/code&gt; and either followed the timeouts until the system came back, or left it running and occasionally checked its output to see if the host is up. But that is unnecessary, you can make ping &lt;code&gt;-a&lt;/code&gt; audible! As soon as the host at &lt;code&gt;IP&lt;/code&gt; is back, &lt;code&gt;ping&lt;/code&gt; will beep!&lt;/p&gt;
&lt;h2&gt;38. List 10 most often used commands.&lt;/h2&gt;
&lt;pre &gt;$ history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head&lt;/pre&gt;
&lt;p&gt;The person who wrote it has the Unix mindset right. He's combining several shell commands to get the result he/she wants.&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;history&lt;/code&gt; outputs all the commands the person has executed. Next, &lt;code&gt;awk&lt;/code&gt; counts how many times the second column &lt;code&gt;$2&lt;/code&gt; appears in the output. Once &lt;code&gt;history&lt;/code&gt; has output all the commands and &lt;code&gt;awk&lt;/code&gt; has counted them, &lt;code&gt;awk&lt;/code&gt; loops over all the commands and outputs the count &lt;code&gt;a[i]&lt;/code&gt; separated by space, followed by the command itself. Then &lt;code&gt;sort&lt;/code&gt; takes this input and sorts numerically &lt;code&gt;-n&lt;/code&gt; and reverses the output &lt;code&gt;-r&lt;/code&gt;, so that most frequent commands were on top. Finally &lt;code&gt;head&lt;/code&gt; outputs the first 10 most frequent history commands.&lt;/p&gt;
&lt;p&gt;If you want to see more than 10 commands (or less), change &lt;code&gt;head&lt;/code&gt; to &lt;code&gt;head -20&lt;/code&gt; for 20 commands or &lt;code&gt;head -5&lt;/code&gt; for 5 commands.&lt;/p&gt;
&lt;h2&gt;39. Check gmail for new mail.&lt;/h2&gt;
&lt;pre &gt;
$ curl -u you@gmail.com --silent "https://mail.google.com/mail/feed/atom" |
  perl -ne \
  '
    print "Subject: $1 " if /&amp;lt;title&gt;(.+?)&amp;lt;\/title&gt;/ &amp;&amp; $title++;
    print "(from $1)\n" if /&amp;lt;email&gt;(.+?)&amp;lt;\/email&gt;/;
  '
&lt;/pre&gt;
&lt;p&gt;Gmail is cool because they offer an Atom feed for the new mail. This one-liner instructs &lt;code&gt;curl&lt;/code&gt; to retrieve the feed and authenticate as &lt;code&gt;you@gmail.com&lt;/code&gt;. You'll be prompted a password after you execute the command. Next it feeds the output to &lt;code&gt;perl&lt;/code&gt;. Perl extracts the title (subject) of each email and the sender's email. These two items are printed to stdout.&lt;/p&gt;
&lt;p&gt;Here is a the output when I run the command,&lt;/p&gt;
&lt;pre &gt;
Subject: i heard you liked windows! (from gates@microsoft.com)
Subject: got root? (from bofh@underground.org)
&lt;/pre&gt;
&lt;h2&gt;40. Watch Star-Wars via telnet.&lt;/h2&gt;
&lt;pre &gt;$ telnet towel.blinkenlights.nl&lt;/pre&gt;
&lt;p&gt;Needs no explaining. Just telnet to the host to watch ASCII Star-Wars.&lt;/p&gt;
&lt;p&gt;And here is another one,&lt;/p&gt;
&lt;pre &gt;$ telnet towel.blinkenlights.nl 666&lt;/pre&gt;
&lt;p&gt;Connecting on port 666 will spit out BOFH excuses.&lt;/p&gt;
&lt;h2&gt;That's it for today.&lt;/h2&gt;
&lt;p&gt;I hope you enjoyed the 4th part of the article. Tune in next time for the 5th part.&lt;/p&gt;
&lt;p&gt;Oh, and I'd love if you &lt;a href="http://twitter.com/pkrumins"&gt;followed me on Twitter!&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=dqjNsh7dF8k:TlyY7pgf0Q0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=dqjNsh7dF8k:TlyY7pgf0Q0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=dqjNsh7dF8k:TlyY7pgf0Q0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=dqjNsh7dF8k:TlyY7pgf0Q0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=dqjNsh7dF8k:TlyY7pgf0Q0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=dqjNsh7dF8k:TlyY7pgf0Q0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=dqjNsh7dF8k:TlyY7pgf0Q0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/dqjNsh7dF8k" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/yet-another-ten-one-liners-from-commandlinefu-explained</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">On Functors</title>
    <id>219</id>
    <updated>2010-05-17T14:31:53Z</updated>
    <published>2010-05-17T13:30:45Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/sm6nLqjn1Cs/on-functors" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yxphiH3knVvZNW1-qSTSowfvBYU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yxphiH3knVvZNW1-qSTSowfvBYU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yxphiH3knVvZNW1-qSTSowfvBYU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yxphiH3knVvZNW1-qSTSowfvBYU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;It's interesting how the term "&lt;strong&gt;functor&lt;/strong&gt;" means completely different things in various programming languages. Take &lt;strong&gt;C++&lt;/strong&gt; for example. Everyone who has mastered C++ knows that you call a class that implements &lt;code&gt;operator()&lt;/code&gt; a functor. Now take &lt;strong&gt;Standard ML&lt;/strong&gt;. In ML functors are mappings from structures to structures. Now &lt;strong&gt;Haskell&lt;/strong&gt;. In Haskell functors are just homomorphisms over containers. And in &lt;strong&gt;Prolog&lt;/strong&gt; functor means the atom at the start of a structure. They all are different. Let's take a closer look at each one.&lt;/p&gt;
&lt;h2&gt;Functors in C++&lt;/h2&gt;
&lt;p&gt;Functors in C++ are short for "&lt;strong&gt;function objects&lt;/strong&gt;." Function objects are instances of C++ classes that have the &lt;code&gt;operator()&lt;/code&gt; defined. If you define &lt;code&gt;operator()&lt;/code&gt; on C++ classes you get objects that act like functions but can also store state. Here is an example,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include &amp;lt;string&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SimpleFunctor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;SimpleFunctor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;name_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;()()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Oh, hello, &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;name_&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;SimpleFunctor&lt;/span&gt; &lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;catonmat&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;sf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// prints &amp;quot;Oh, hello, catonmat&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Notice how I was able to call &lt;code&gt;sf()&lt;/code&gt; in the &lt;code&gt;main&lt;/code&gt; function, even though &lt;code&gt;sf&lt;/code&gt; was an object? That's because I defined &lt;code&gt;operator()&lt;/code&gt; in &lt;code&gt;SimpleFunctor&lt;/code&gt;'s class.&lt;/p&gt;
&lt;p&gt;Most often functors in C++ are used as predicates, fake closures or comparison functions in STL algorithms. Here is another example. Suppose you have a list of integers and you wish to find the sum of all even ones, and the sum of all odd ones. Perfect job for a functor and &lt;code&gt;for_each&lt;/code&gt; algorithm.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="cp"&gt;#include &amp;lt;algorithm&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include &amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;#include &amp;lt;list&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EvenOddFunctor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;even_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;odd_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;EvenOddFunctor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;even_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;odd_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;even_&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;odd_&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;even_sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;even_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;odd_sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;odd_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EvenOddFunctor&lt;/span&gt; &lt;span class="n"&gt;evenodd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="n"&gt;evenodd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;for_each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;my_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                  &lt;span class="n"&gt;evenodd&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Sum of evens: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;evenodd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;even_sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Sum of odds: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;evenodd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;odd_sum&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// output:&lt;/span&gt;
    &lt;span class="c1"&gt;// Sum of evens: 30&lt;/span&gt;
    &lt;span class="c1"&gt;// Sum of odds: 25&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Here an instance of an &lt;code&gt;EvenOddFunctor&lt;/code&gt; gets passed to &lt;code&gt;for_each&lt;/code&gt; algorithm. The &lt;code&gt;for_each&lt;/code&gt; algorithm iterates over each element in &lt;code&gt;my_list&lt;/code&gt; and calls the functor. After it's done, it returns a copy of &lt;code&gt;evenodd&lt;/code&gt; functor that contains the sum of evens and odds.&lt;/p&gt;
&lt;h2&gt;Functors in Standard ML&lt;/h2&gt;
&lt;p&gt;Vaguely talking in object-oriented terms, functors in ML are generic implementations of interfaces. In ML terms, functors are part of ML module system and they allow to compose structures.&lt;/p&gt;
&lt;p&gt;Here is an example, suppose you want to write a plugin system and you wish all the plugins to implement the required interface, which, for simplicity, includes only the &lt;code&gt;perform&lt;/code&gt; function. In ML you can first define a signature for plugins,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="k"&gt;sig&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;unit&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now that we have defined an interface (signature) for plugins, we can implement two Plugins, let's say &lt;code&gt;LoudPlugin&lt;/code&gt; and &lt;code&gt;SilentPlugin&lt;/code&gt;. The implementation is done via structures,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="n"&gt;structure&lt;/span&gt; &lt;span class="nc"&gt;LoudPlugin&lt;/span&gt; &lt;span class="o"&gt;:&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;DOING JOB LOUDLY!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;And the SilentPlugin,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="n"&gt;structure&lt;/span&gt; &lt;span class="nc"&gt;SilentPlugin&lt;/span&gt; &lt;span class="o"&gt;:&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;doing job silently&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now we get to functors. Remember functors in ML take structures as their arguments, so we can write one that takes &lt;code&gt;Plugin&lt;/code&gt; as its argument,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="k"&gt;functor&lt;/span&gt; &lt;span class="nc"&gt;Performer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;P&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Plugin&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This functor takes &lt;code&gt;Plugin&lt;/code&gt; as &lt;code&gt;P&lt;/code&gt; argument, and uses it in the &lt;code&gt;job&lt;/code&gt; function, that calls &lt;code&gt;P&lt;/code&gt; plugin's &lt;code&gt;perform&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Now let's use the &lt;code&gt;Performer&lt;/code&gt; functor. Remember that a functor returns a structure,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="n"&gt;structure&lt;/span&gt; &lt;span class="nc"&gt;LoudPerformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Performer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;LoudPlugin&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;structure&lt;/span&gt; &lt;span class="nc"&gt;SilentPerformer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Performer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SilentPlugin&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="nn"&gt;LoudPerformer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nn"&gt;SilentPerformer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;job&lt;/span&gt; &lt;span class="bp"&gt;()&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This outputs,&lt;/p&gt;
&lt;pre &gt;
DOING JOB LOUDLY!
doing job silently
&lt;/pre&gt;
&lt;p&gt;This is probably the simplest possible example of Standard ML functors.&lt;/p&gt;
&lt;h2&gt;Functors in Haskell&lt;/h2&gt;
&lt;p&gt;Functors in Haskell is what real functors are supposed to be. Haskell functors resemble mathematical functors from category theory. In category theory a functor F is a mapping between two categories such that the structure of the category being mapped over is preserved, in other words, it's a homomorphism between two categories.&lt;/p&gt;
&lt;p&gt;In Haskell this definition is implemented as a simple type class,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Looking back at ML example, a type class in Haskell is like a signature, except it's defined on types. It defines what operations a type has to implement to be an instance of this class. In this case, however, the &lt;code&gt;Functor&lt;/code&gt; is not defined over types but over type constructors &lt;code&gt;f&lt;/code&gt;. It says, a &lt;code&gt;Functor&lt;/code&gt; is something that implements the &lt;code&gt;fmap&lt;/code&gt; function that takes a function from type &lt;code&gt;a&lt;/code&gt; to type &lt;code&gt;b&lt;/code&gt;, and a value of type &lt;code&gt;f a&lt;/code&gt; (a type constructed from type constructor &lt;code&gt;f&lt;/code&gt; applied to type &lt;code&gt;a&lt;/code&gt;) and returns a value of type &lt;code&gt;f b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To understand what it does, think of &lt;code&gt;fmap&lt;/code&gt; as a function that applies an operation to each element in some kind of a container.&lt;/p&gt;
&lt;p&gt;The simplest example of functors is regular lists and the &lt;code&gt;map&lt;/code&gt; function that maps a function to each element in the list.&lt;/p&gt;
&lt;pre &gt;
Prelude&gt; map (+1) [1,2,3,4,5]
[2,3,4,5,6]
&lt;/pre&gt;
&lt;p&gt;In this simple example, the &lt;code&gt;Functor&lt;/code&gt;'s &lt;code&gt;fmap&lt;/code&gt; function is just &lt;code&gt;map&lt;/code&gt; and type constructor &lt;code&gt;f&lt;/code&gt; is &lt;code&gt;[]&lt;/code&gt; - the list type constructor. Therefore the &lt;code&gt;Functor&lt;/code&gt; instance for lists is defined as&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="kt"&gt;[]&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
  &lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Let's see if it really is true by using &lt;code&gt;fmap&lt;/code&gt; instead of &lt;code&gt;map&lt;/code&gt; in the previous example,&lt;/p&gt;
&lt;pre &gt;
Prelude&gt; fmap (+1) [1,2,3,4,5]
[2,3,4,5,6]
&lt;/pre&gt;
&lt;p&gt;But notice that Functor definition does not say anything about preserving the structure! Therefore any sensible functor must satisfy the functor laws, which are part of the definition of the mathematical functor, implicitly. There are two rules on &lt;code&gt;fmap&lt;/code&gt;:&lt;/p&gt;
&lt;pre &gt;
fmap id = id
fmap (g . h) = fmap g . fmap h
&lt;/pre&gt;
&lt;p&gt;The first rule says that mapping the identity function over every element in a container has no effect. The second rule says that a composition of two functions over every item in a container is the same as first mapping one function, and then mapping the other.&lt;/p&gt;
&lt;p&gt;Another example of Functors that illustrate them the most vividly is operations over trees. Think of a tree as a container, then &lt;code&gt;fmap&lt;/code&gt; maps a function over tree values, while preserving the tree's structure.&lt;/p&gt;
&lt;p&gt;Let's define a Tree first,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Leaf&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
              &lt;span class="kr"&gt;deriving&lt;/span&gt; &lt;span class="kt"&gt;Show&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This definition says that a &lt;code&gt;Tree&lt;/code&gt; of type &lt;code&gt;a&lt;/code&gt; is either a &lt;code&gt;Node&lt;/code&gt; of two &lt;code&gt;Tree&lt;/code&gt;s (left and right branches) or a &lt;code&gt;Leaf&lt;/code&gt;. The &lt;code&gt;deriving Show&lt;/code&gt; expression allows us to inspect the Tree via &lt;code&gt;show&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Now we can define a &lt;code&gt;Functor&lt;/code&gt; over &lt;code&gt;Tree&lt;/code&gt;s,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kr"&gt;instance&lt;/span&gt; &lt;span class="kt"&gt;Functor&lt;/span&gt; &lt;span class="kt"&gt;Tree&lt;/span&gt; &lt;span class="kr"&gt;where&lt;/span&gt;
    &lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Leaf&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Leaf&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Node&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmap&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This definition says, that &lt;code&gt;fmap&lt;/code&gt; of function &lt;code&gt;g&lt;/code&gt; over a &lt;code&gt;Leaf&lt;/code&gt; with value &lt;code&gt;v&lt;/code&gt; is just a &lt;code&gt;Leaf&lt;/code&gt; of &lt;code&gt;g&lt;/code&gt; applied to &lt;code&gt;v&lt;/code&gt;. And &lt;code&gt;fmap&lt;/code&gt; of &lt;code&gt;g&lt;/code&gt; over a &lt;code&gt;Node&lt;/code&gt; with left &lt;code&gt;l&lt;/code&gt; and right &lt;code&gt;r&lt;/code&gt; branches is just a &lt;code&gt;Node&lt;/code&gt; of &lt;code&gt;fmap&lt;/code&gt; applied to the values of left and right branches.&lt;/p&gt;
&lt;p&gt;Now let's illustrate how fmap works on trees. Let's construct a tree with String leaves and map the length function over them to find out the length of each leaf.&lt;/p&gt;
&lt;pre &gt;
Prelude&gt; let tree = (Node (Node (Leaf "hello") (Leaf "foo")) (Leaf "baar"))
Prelude&gt; fmap length tree
Node (Node (Leaf 5) (Leaf 3)) (Leaf 4)
&lt;/pre&gt;
&lt;p&gt;Here I constructed the following tree,&lt;/p&gt;
&lt;pre &gt;
           *
          / \
         /   \
        *  "baar"
       / \
      /   \
     /     \
    /       \
 "hello"  "foo"
&lt;/pre&gt;
&lt;p&gt;And mapped &lt;code&gt;length&lt;/code&gt; function over it, producing,&lt;/p&gt;
&lt;pre &gt;
           *
          / \
         /   \
        *     4
       / \     
      /   \
     /     \
    /       \
   5         3
&lt;/pre&gt;
&lt;p&gt;Another way of saying what &lt;code&gt;fmap&lt;/code&gt; does is that is &lt;strong&gt;lifts&lt;/strong&gt; a function from the "normal world" into the "&lt;code&gt;f&lt;/code&gt; world."&lt;/p&gt;
&lt;p&gt;In fact Functor is the most fundamental type class in Haskell because Monads, Applicatives and Arrows are all Functors. As I like to say it, Haskell starts where the functors start.&lt;/p&gt;
&lt;p&gt;If you wish to learn more about Haskell type classes, start with the excellent article &lt;a href="http://www.catonmat.net/docs/typeclassopedia.pdf"&gt;Typeclassopedia&lt;/a&gt; (starts at page 17).&lt;/p&gt;
&lt;h2&gt;Functors in Prolog&lt;/h2&gt;
&lt;p&gt;Finally, functors in Prolog. Functors in Prolog are the simplest of all. They refer to two things. The first is the atom at the start of the structure. Here is an example, given an expression,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="s-Atom"&gt;?-&lt;/span&gt; &lt;span class="nf"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s-Atom"&gt;mary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s-Atom"&gt;pizza&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;the functor is the first atom - &lt;code&gt;likes&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second is built-in predicate called &lt;code&gt;functor&lt;/code&gt;. It returns the arity and the functor of a structure. For example,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="s-Atom"&gt;?-&lt;/span&gt; &lt;span class="nf"&gt;functor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;likes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s-Atom"&gt;mary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s-Atom"&gt;pizza&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;Functor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Arity&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
&lt;span class="nv"&gt;Functor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s-Atom"&gt;likes&lt;/span&gt;
&lt;span class="nv"&gt;Arity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That's it for functors in Prolog.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This article demonstrated how a simple term like "functor" can refer to completely different things in various programming languages. Therefore when you hear a the term "functor", it's important to know the context it's being mentioned in.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sm6nLqjn1Cs:yycUuX5ASQ0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sm6nLqjn1Cs:yycUuX5ASQ0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=sm6nLqjn1Cs:yycUuX5ASQ0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sm6nLqjn1Cs:yycUuX5ASQ0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=sm6nLqjn1Cs:yycUuX5ASQ0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=sm6nLqjn1Cs:yycUuX5ASQ0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=sm6nLqjn1Cs:yycUuX5ASQ0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/sm6nLqjn1Cs" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/on-functors</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Turn any Linux computer into SOCKS5 proxy in one command</title>
    <id>216</id>
    <updated>2010-05-07T12:18:07Z</updated>
    <published>2010-05-06T19:20:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/4zYK7bywA9E/linux-socks5-proxy" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/U7kfa7ZXIOKc7gsONKEPvEeZgFU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/U7kfa7ZXIOKc7gsONKEPvEeZgFU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/U7kfa7ZXIOKc7gsONKEPvEeZgFU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/U7kfa7ZXIOKc7gsONKEPvEeZgFU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I thought I'd do a shorter article on catonmat this time. It goes hand in hand with my upcoming article series on "&lt;strong&gt;100% technical guide to anonymity&lt;/strong&gt;" and it's much easier to write larger articles in smaller pieces. Then I can edit them together and produce the final article.&lt;/p&gt;
&lt;p&gt;This article will be interesting for those who didn't know it already -- you can turn any Linux computer into a SOCKS5 (and SOCKS4) proxy in just one command:&lt;/p&gt;
&lt;pre &gt;ssh -N -D 0.0.0.0:1080 localhost&lt;/pre&gt;
&lt;p&gt;And it doesn't require root privileges. The &lt;code&gt;ssh&lt;/code&gt; command starts up dynamic &lt;code&gt;-D&lt;/code&gt; port forwarding on port &lt;code&gt;1080&lt;/code&gt; and talks to the clients via SOCSK5 or SOCKS4 protocols, just like a regular SOCKS5 proxy would! The &lt;code&gt;-N&lt;/code&gt; option makes sure ssh stays idle and doesn't execute any commands on localhost.&lt;/p&gt;
&lt;p&gt;If you also wish the command to go into background as a daemon, then add &lt;code&gt;-f&lt;/code&gt; option:&lt;/p&gt;
&lt;pre &gt;ssh -f -N -D 0.0.0.0:1080 localhost&lt;/pre&gt;
&lt;p&gt;To use it, just make your software use SOCKS5 proxy on your Linux computer's IP, port 1080, and you're done, all your requests now get proxied.&lt;/p&gt;
&lt;p&gt;Access control can be implemented via &lt;code&gt;iptables&lt;/code&gt;. For example, to allow only people from the ip &lt;code&gt;1.2.3.4&lt;/code&gt; to use the SOCKS5 proxy, add the following &lt;code&gt;iptables&lt;/code&gt; rules:&lt;/p&gt;
&lt;pre &gt;
iptables -A INPUT --src 1.2.3.4 -p tcp --dport 1080 -j ACCEPT
iptables -A INPUT -p tcp --dport 1080 -j REJECT
&lt;/pre&gt;
&lt;p&gt;The first rule says, allow anyone from &lt;code&gt;1.2.3.4&lt;/code&gt; to connect to port &lt;code&gt;1080&lt;/code&gt;, and the other rule says, deny everyone else from connecting to port &lt;code&gt;1080&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Surely, executing &lt;code&gt;iptables&lt;/code&gt; requires root privileges. If you don't have root privileges, and you don't want to leave your proxy open (and you really don't want to do that), you'll have to use some kind of a simple TCP proxy wrapper to do access control.&lt;/p&gt;
&lt;p&gt;Here, I wrote one in Perl. It's called &lt;code&gt;tcp-proxy.pl&lt;/code&gt; and it uses &lt;code&gt;IO::Socket::INET&lt;/code&gt; to abstract sockets, and &lt;code&gt;IO::Select&lt;/code&gt; to do connection multiplexing.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="lotsofcode"&gt;&lt;span class="c1"&gt;#!/usr/bin/perl&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;IO::Socket::&lt;/span&gt;&lt;span class="n"&gt;INET&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;IO::&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@allowed_ips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;1.2.3.4&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;5.6.7.8&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;192.168.1.2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$ioset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IO::&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;%socket_map&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$debug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;new_conn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nn"&gt;IO::Socket::&lt;/span&gt;&lt;span class="n"&gt;INET&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;PeerAddr&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;PeerPort&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$port&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Unable to connect to $host:$port: $!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;new_server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;@_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IO::Socket::&lt;/span&gt;&lt;span class="n"&gt;INET&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;LocalAddr&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;LocalPort&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ReuseAddr&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Listen&lt;/span&gt;    &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;die&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Unable to listen on $host:$port: $!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;new_connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Connection from $client_ip denied.\n&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$debug&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Connection from $client_ip accepted.\n&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$debug&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$remote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_conn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;55555&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$ioset&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$ioset&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;close_connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$remote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    
    &lt;span class="nv"&gt;$ioset&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$ioset&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;delete&lt;/span&gt; &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nb"&gt;delete&lt;/span&gt; &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Connection from $client_ip closed.\n&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$debug&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;client_ip&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;inet_ntoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sockaddr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;sub &lt;/span&gt;&lt;span class="nf"&gt;client_allowed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$client_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt; &lt;span class="ow"&gt;eq&lt;/span&gt; &lt;span class="nv"&gt;$client_ip&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nv"&gt;@allowed_ips&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Starting a server on 0.0.0.0:1080\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;0.0.0.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$ioset&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$socket&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ioset&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;can_read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$socket&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;new_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nb"&gt;exists&lt;/span&gt; &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$socket&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$remote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$socket_map&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$socket&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$socket&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;sysread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$remote&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;syswrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;close_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;To use it, you'll have to make a change to the previous configuration. Instead of running ssh SOCKS5 proxy on &lt;code&gt;0.0.0.0:1080&lt;/code&gt;, you'll need to run it on &lt;code&gt;localhost:55555&lt;/code&gt;,&lt;/p&gt;
&lt;pre &gt;ssh -f -N -D 55555 localhost&lt;/pre&gt;
&lt;p&gt;After that, run the &lt;code&gt;tcp-proxy.pl&lt;/code&gt;,&lt;/p&gt;
&lt;pre &gt;perl tcp-proxy.pl &amp;&lt;/pre&gt;
&lt;p&gt;The TCP proxy will start listening on &lt;code&gt;0.0.0.0:1080&lt;/code&gt; and will redirect only the allowed IPs in &lt;code&gt;@allowed_ips&lt;/code&gt; list to &lt;code&gt;localhost:55555&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another possibility is to use another computer instead of your own as exit node. What I mean is you can do the following:&lt;/p&gt;
&lt;pre &gt;ssh -f -N -D 1080 other_computer.com&lt;/pre&gt;
&lt;p&gt;This will set up a SOCKS5 proxy on &lt;code&gt;localhost:1080&lt;/code&gt; but when you use it, ssh will automatically tunnel your requests (encrypted) via &lt;code&gt;other_computer.com&lt;/code&gt;. This way you can hide what you're doing on the Internet from anyone who might be sniffing your link. They will see that you're doing something but the traffic will be encrypted so they won't be able to tell what you're doing.&lt;/p&gt;
&lt;p&gt;That's it. You're now the proxy king!&lt;/p&gt;
&lt;h2&gt;Thanks To Vitalik&lt;/h2&gt;
&lt;p&gt;Special thanks to Vitalik from "&lt;a href="http://www.itransition.com/"&gt;Itransition company&lt;/a&gt;" for helpful tips!&lt;/p&gt;
&lt;div class="download"&gt;&lt;div class="download-title"&gt;&lt;p&gt;Download tcp-proxy.pl&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Download link: &lt;a href="/download/tcp-proxy.pl" title="Download &amp;quot;tcp proxy (tcp-proxy.pl)&amp;quot;"&gt;tcp proxy (tcp-proxy.pl)&lt;/a&gt;&lt;br&gt;
Download URL: &lt;code&gt;http://www.catonmat.net/download/tcp-proxy.pl&lt;/code&gt;&lt;br&gt;
Downloaded: 594 times&lt;/p&gt;
&lt;p&gt;I also pushed the tcp-proxy.pl to GitHub: &lt;a href="http://github.com/pkrumins/perl-tcp-proxy"&gt;tcp-proxy.pl on GitHub&lt;/a&gt;. This project is also pretty nifty to generalize and make a program that redirects between any number of hosts:ports, not just two.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;PS. I will probably also write "&lt;strong&gt;A definitive guide to ssh port forwarding&lt;/strong&gt;" some time in the future because it's an interesting but little understood topic.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4zYK7bywA9E:UGQY8vxqfK8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4zYK7bywA9E:UGQY8vxqfK8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=4zYK7bywA9E:UGQY8vxqfK8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4zYK7bywA9E:UGQY8vxqfK8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=4zYK7bywA9E:UGQY8vxqfK8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=4zYK7bywA9E:UGQY8vxqfK8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=4zYK7bywA9E:UGQY8vxqfK8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/4zYK7bywA9E" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/linux-socks5-proxy</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">A HTTP Proxy Server in 20 Lines of node.js Code</title>
    <id>215</id>
    <updated>2010-06-27T16:55:31Z</updated>
    <published>2010-04-28T11:10:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/kn7okZClh-E/http-proxy-in-nodejs" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BMCaNUpm_3HDI9bK_APHWiOB9Bk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BMCaNUpm_3HDI9bK_APHWiOB9Bk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BMCaNUpm_3HDI9bK_APHWiOB9Bk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BMCaNUpm_3HDI9bK_APHWiOB9Bk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;host&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is just amazing. In 20 lines of &lt;a href="http://nodejs.org/"&gt;node.js&lt;/a&gt; code and 10 minutes of time I was able to write a HTTP proxy. And it scales well, too. It's not a blocking HTTP proxy, it's event driven and asynchronous, meaning hundreds of people can use simultaneously and it will work well.&lt;/p&gt;
&lt;p&gt;To get the proxy running all you have to do is download node.js, compile it, and run the proxy program via the &lt;code&gt;node&lt;/code&gt; program:&lt;/p&gt;
&lt;pre &gt;
$ ./configure --prefix=/home/pkrumins/installs/nodejs-0.1.92
$ make
$ make install

$ PATH=$PATH:/home/pkrumins/installs/nodejs-0.1.92/bin

$ node proxy.js
&lt;/pre&gt;
&lt;p&gt;And from here you can take this proxy wherever your imagination takes. For example, you can start by adding logging:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre &gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sys&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;host&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Next, you can add a regex-based host blacklist in 15 additional lines:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="lotsofcode"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sys&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;blacklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;watchFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./blacklist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Updating blacklist.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;blacklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./blacklist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Denied: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;host&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary);&lt;/span&gt;
&lt;span class="s1"&gt;  });&lt;/span&gt;
&lt;span class="s1"&gt;  request.addListener(&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now to block proxy users from using Facebook, just echo &lt;code&gt;facebook.com&lt;/code&gt; to &lt;code&gt;blacklist&lt;/code&gt; file:&lt;/p&gt;
&lt;pre &gt;
$ echo 'facebook.com' &gt;&gt; blacklist
&lt;/pre&gt;
&lt;p&gt;The proxy server will automatically notice the changes to the file and update the blacklist.&lt;/p&gt;
&lt;p&gt;Surely, a proxy server without IP control is no proxy server, so let's add that as well:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="lotsofcode"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sys&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;blacklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;iplist&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;watchFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./blacklist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;watchFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./iplist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;update_iplist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Updating blacklist.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;blacklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./blacklist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;update_iplist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Updating iplist.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;iplist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./iplist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;allowed_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;iplist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iplist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;allowed_ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allowed_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;IP &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; is not allowed&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Denied: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;host&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;update_iplist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;By default the proxy server will not allow any connections, so add all the IPs you want the proxy to be accessible from to &lt;code&gt;iplist&lt;/code&gt; file:&lt;/p&gt;
&lt;pre &gt;
$ echo '1.2.3.4' &gt;&gt; iplist
&lt;/pre&gt;
&lt;p&gt;Finally, let's refactor the code a little:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="lotsofcode"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sys&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;sys&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;fs&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;blacklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;iplist&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;watchFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./blacklist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;watchFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./iplist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;update_iplist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Updating blacklist.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;blacklist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./blacklist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;update_iplist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Updating iplist.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;iplist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./iplist&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ip_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;iplist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iplist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;host_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blacklist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ip_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;IP &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; is not allowed to use this proxy&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;host_allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Host &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; has been denied by proxy configuration&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;deny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;: &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;host&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;proxy_request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;response&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proxy_response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;data&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;binary);&lt;/span&gt;
&lt;span class="s1"&gt;  });&lt;/span&gt;
&lt;span class="s1"&gt;  request.addListener(&amp;#39;&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;proxy_request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;update_blacklist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;update_iplist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Again, it's amazing how fast you can write server software in node.js and JavaScript. It would have probably taken me a day to write the same in C. I love how fast you can prototype the software nowadays.&lt;/p&gt;
&lt;div class="download"&gt;&lt;div class="download-title"&gt;&lt;p&gt;Download proxy.js&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Download link: &lt;a href="/download/proxy.js" title="Download &amp;quot;proxy server written in node.js&amp;quot;"&gt;proxy server written in node.js&lt;/a&gt;&lt;br&gt;
Download URL: &lt;code&gt;http://www.catonmat.net/download/proxy.js&lt;/code&gt;&lt;br&gt;
Downloaded: 1018 times&lt;/p&gt;
&lt;p&gt;I am gonna build this proxy up, so I also put it on GitHub: &lt;a href="http://github.com/pkrumins/nodejs-proxy"&gt;proxy.js on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Happy proxying!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kn7okZClh-E:wpfRZzFuuKk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kn7okZClh-E:wpfRZzFuuKk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=kn7okZClh-E:wpfRZzFuuKk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kn7okZClh-E:wpfRZzFuuKk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=kn7okZClh-E:wpfRZzFuuKk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=kn7okZClh-E:wpfRZzFuuKk:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=kn7okZClh-E:wpfRZzFuuKk:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/kn7okZClh-E" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/http-proxy-in-nodejs</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Another Ten One-Liners from CommandLineFu Explained</title>
    <id>212</id>
    <updated>2010-04-30T11:54:34Z</updated>
    <published>2010-04-20T21:05:00Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/u10fej7POxc/another-ten-one-liners-from-commandlinefu-explained" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/L430a-kPQU0Wd6taq1UMysJiMVk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/L430a-kPQU0Wd6taq1UMysJiMVk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/L430a-kPQU0Wd6taq1UMysJiMVk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/L430a-kPQU0Wd6taq1UMysJiMVk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/blog/wp-content/uploads/2010/03/commandlinefu-explained.jpg" alt="CommandLineFu Explained" class="post-icon" align="left"&gt;Another week and another top ten one-liners from &lt;a href="http://www.commandlinefu.com/"&gt;commandlinefu&lt;/a&gt; explained.&lt;/p&gt;
&lt;p&gt;This is the third post in the series already, covering one-liners 21-30. See the previous two posts for the introduction of the series and one-liners 1-20:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained"&gt;Part I: Top Ten One-Liners from CommandLineFu Explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/the-next-ten-one-liners-from-commandlinefu-explained"&gt;Part II: The Next Ten One-Liners from CommandLineFu Explained&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://rus-linux.net/nlib.php?name=/MyLDP/consol/oneliners21_30.html"&gt;Russian translation now available.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;#21. Display currently mounted file systems nicely&lt;/h2&gt;
&lt;pre &gt;
$ mount | column -t
&lt;/pre&gt;
&lt;p&gt;The file systems are not that important here. The &lt;code&gt;column -t&lt;/code&gt; command is what is important. It takes the input and formats it into multiple columns so that all columns were aligned vertically.&lt;/p&gt;
&lt;p&gt;Here is how the mounted filesystem list looks without &lt;code&gt;column -t&lt;/code&gt; command:&lt;/p&gt;
&lt;pre &gt;
$ mount

/dev/root on / type ext3 (rw)
/proc on /proc type proc (rw)
/dev/mapper/lvmraid-home on /home type ext3 (rw,noatime)
&lt;/pre&gt;
&lt;p&gt;And now with &lt;code&gt;column -t&lt;/code&gt; command:&lt;/p&gt;
&lt;pre &gt;
$ mount | column -t

/dev/root                 on  /      type  ext3   (rw)
/proc                     on  /proc  type  proc   (rw)
/dev/mapper/lvmraid-home  on  /home  type  ext3   (rw,noatime)
&lt;/pre&gt;
&lt;p&gt;You can improve this one-liner now by also adding column titles:&lt;/p&gt;
&lt;pre &gt;
$ (echo "DEVICE - PATH - TYPE FLAGS" &amp;&amp; mount) | column -t

DEVICE                    -   PATH   -     TYPE   FLAGS
/dev/root                 on  /      type  ext3   (rw)
/proc                     on  /proc  type  proc   (rw)
/dev/mapper/lvmraid-home  on  /home  type  ext3   (rw,noatime)
&lt;/pre&gt;
&lt;p&gt;Columns 2 and 4 are not really necessary. We can use &lt;code&gt;awk&lt;/code&gt; text processing utility to get rid of them:&lt;/p&gt;
&lt;pre &gt;
$ (echo "DEVICE PATH TYPE FLAGS" &amp;&amp; mount | awk '$2=$4="";1') | column -t

DEVICE                    PATH   TYPE   FLAGS
/dev/root                 /      ext3   (rw)
/proc                     /proc  proc   (rw)
/dev/mapper/lvmraid-home  /home  ext3   (rw,noatime)
&lt;/pre&gt;
&lt;p&gt;Finally, we can make it an alias so that we always enjoyed the nice output from mount. Let's call this alias &lt;code&gt;nicemount&lt;/code&gt;:&lt;/p&gt;
&lt;pre &gt;
$ nicemount() { (echo "DEVICE PATH TYPE FLAGS" &amp;&amp; mount | awk '$2=$4="";1') | column -t; }
&lt;/pre&gt;
&lt;p&gt;Let's try it out:&lt;/p&gt;
&lt;pre &gt;
$ nicemount

DEVICE                    PATH   TYPE   FLAGS
/dev/root                 /      ext3   (rw)
/proc                     /proc  proc   (rw)
/dev/mapper/lvmraid-home  /home  ext3   (rw,noatime)
&lt;/pre&gt;
&lt;p&gt;It works!&lt;/p&gt;
&lt;h2&gt;#22. Run the previous shell command but replace every "foo" with "bar"&lt;/h2&gt;
&lt;pre &gt;$ !!:gs/foo/bar&lt;/pre&gt;
&lt;p&gt;I explained this type of one-liners in &lt;a href="http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained"&gt;one-liner #5 already&lt;/a&gt;. Please take a look for a longer discussion.&lt;/p&gt;
&lt;p&gt;To summarize, what happens here is that the &lt;code&gt;!!&lt;/code&gt; recalls the previous executed shell command and &lt;code&gt;:gs/foo/bar&lt;/code&gt; substitutes (the &lt;code&gt;:s&lt;/code&gt; flag) all (the &lt;code&gt;g&lt;/code&gt; flag) occurrences of &lt;code&gt;foo&lt;/code&gt; with &lt;code&gt;bar&lt;/code&gt;. The &lt;code&gt;!!&lt;/code&gt; construct is called an event designator.&lt;/p&gt;
&lt;h2&gt;#23. Top for files&lt;/h2&gt;
&lt;pre &gt;$ watch -d -n 1 'df; ls -FlAt /path'&lt;/pre&gt;
&lt;p&gt;This one-liner watches for file changes in directory &lt;code&gt;/path&lt;/code&gt;. It uses the &lt;code&gt;watch&lt;/code&gt; command that executes the given command periodically. The &lt;code&gt;-d&lt;/code&gt; flag tells &lt;code&gt;watch&lt;/code&gt; to display differences between the command calls (so you saw what files get added or removed in &lt;code&gt;/path&lt;/code&gt;). The &lt;code&gt;-n 1&lt;/code&gt; flag tells it to execute the command every second.&lt;/p&gt;
&lt;p&gt;The command to execute is &lt;code&gt;df; ls -FlAt /path&lt;/code&gt; that is actually two commands, executed one after other. First, &lt;code&gt;df&lt;/code&gt; outputs the filesystem disk space usage, and then &lt;code&gt;ls -FlAt&lt;/code&gt; lists the files in &lt;code&gt;/path&lt;/code&gt;. The &lt;code&gt;-F&lt;/code&gt; argument to &lt;code&gt;ls&lt;/code&gt; tells it to classify files, appending &lt;code&gt;*/=&gt;@|&lt;/code&gt; to the filenames to indicate whether they are executables &lt;code&gt;*&lt;/code&gt;, directories &lt;code&gt;/&lt;/code&gt;, sockets &lt;code&gt;=&lt;/code&gt;, doors &lt;code&gt;&gt;&lt;/code&gt;, symlinks &lt;code&gt;@&lt;/code&gt;, or named pipes &lt;code&gt;|&lt;/code&gt;. The &lt;code&gt;-l&lt;/code&gt; argument lists all files, &lt;code&gt;-A&lt;/code&gt; hides &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt;, and &lt;code&gt;-t&lt;/code&gt; sorts the files by time.&lt;/p&gt;
&lt;p&gt;Special note about doors - they are Solaris thing that act like pipes, except they launch the program that is supposed to be the receiving party. A plain pipe would block until the other party opens it, but a door launches the other party itself.&lt;/p&gt;
&lt;p&gt;Actually the output is nicer if you specify &lt;code&gt;-h&lt;/code&gt; argument to &lt;code&gt;df&lt;/code&gt; so it was human readable. You can also join the arguments to &lt;code&gt;watch&lt;/code&gt; together, making them &lt;code&gt;-dn1&lt;/code&gt;. Here is the final version:&lt;/p&gt;
&lt;pre &gt;
$ watch -dn1 'df -h; ls -FlAt /path'
&lt;/pre&gt;
&lt;p&gt;Another note - &lt;code&gt;-d&lt;/code&gt; in BSD is &lt;code&gt;--differences&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;#24. Mount a remote folder through SSH&lt;/h2&gt;
&lt;pre &gt;$ sshfs name@server:/path/to/folder /path/to/mount/point&lt;/pre&gt;
&lt;p&gt;That's right, you can mount a remote directory locally via SSH! You'll first need to install two programs however:&lt;/p&gt;
&lt;ul&gt;  &lt;li&gt;&lt;a href="http://fuse.sourceforge.net/"&gt;FUSE&lt;/a&gt; that allows to implement filesystems in userspace programs, and&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://fuse.sourceforge.net/sshfs.html"&gt;sshfs&lt;/a&gt; client that uses FUSE and &lt;code&gt;sftp&lt;/code&gt; (secure ftp - comes with OpenSSH, and is on your system already) to access the remote host.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that's it, now you can use &lt;code&gt;sshfs&lt;/code&gt; to mount remote directories via SSH.&lt;/p&gt;
&lt;p&gt;To unmount, use &lt;code&gt;fusermount&lt;/code&gt;:&lt;/p&gt;
&lt;pre &gt;fusermount -u /path/to/mount/point&lt;/pre&gt;
&lt;h2&gt;#25. Read Wikipedia via DNS&lt;/h2&gt;
&lt;pre &gt;$ dig +short txt &amp;lt;keyword&gt;.wp.dg.cx&lt;/pre&gt;
&lt;p&gt;This is probably the most interesting one-liner today. &lt;a href="https://dgl.cx/"&gt;David Leadbeater&lt;/a&gt; created a &lt;a href="https://dgl.cx/wikipedia-dns"&gt;DNS server&lt;/a&gt;, which when queried the TXT record type, returns a short plain-text version of a Wikipedia article. Here is his &lt;a href="http://dgl.cx/2008/11/wpdns-pres/"&gt;presentation&lt;/a&gt; on he did it.&lt;/p&gt;
&lt;p&gt;Here is an example, let's find out what "hacker" means:&lt;/p&gt;
&lt;pre &gt;
$ dig +short txt hacker.wp.dg.cx

"Hacker may refer to: Hacker (computer security), someone involved
in computer security/insecurity, Hacker (programmer subculture), a
programmer subculture originating in the US academia in the 1960s,
which is nowadays mainly notable for the free software/" "open
source movement, Hacker (hobbyist), an enthusiastic home computer
hobbyist http://a.vu/w:Hacker"
&lt;/pre&gt;
&lt;p&gt;The one-liner uses &lt;code&gt;dig&lt;/code&gt;, the standard sysadmin's utility for DNS troubleshooting to do the DNS query. The &lt;code&gt;+short&lt;/code&gt; option makes it output only the returned text response, and &lt;code&gt;txt&lt;/code&gt; makes it query the TXT record type.&lt;/p&gt;
&lt;p&gt;This one-liner is actually alias worthy, so let's make an alias:&lt;/p&gt;
&lt;pre &gt;wiki() { dig +short txt $1.wp.dg.cx; }&lt;/pre&gt;
&lt;p&gt;Try it out:&lt;/p&gt;
&lt;pre &gt;
$ wiki hacker

"Hacker may refer to: Hacker (computer security), ..."
&lt;/pre&gt;
&lt;p&gt;It works!&lt;/p&gt;
&lt;p&gt;If you don't have &lt;code&gt;dig&lt;/code&gt;, you may also use &lt;code&gt;host&lt;/code&gt; that also performs DNS lookups:&lt;/p&gt;
&lt;pre &gt;host -t txt hacker.wp.dg.cx&lt;/pre&gt;
&lt;h2&gt;#26. Download a website recursively with wget&lt;/h2&gt;
&lt;pre &gt;$ wget --random-wait -r -p -e robots=off -U Mozilla www.example.com&lt;/pre&gt;
&lt;p&gt;This one-liner does what it says. Here is the explanation of the arguments:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;code&gt;--random-wait&lt;/code&gt; - wait between 0.5 to 1.5 seconds between requests.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;-r&lt;/code&gt; - turn on recursive retrieving.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;-e robots=off&lt;/code&gt; - ignore robots.txt.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;-U Mozilla&lt;/code&gt; - set the "User-Agent" header to "Mozilla". Though a better choice is a real User-Agent like "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729)".&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some other useful options are:&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;code&gt;--limit-rate=20k&lt;/code&gt; - limits download speed to 20kbps.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;-o logfile.txt&lt;/code&gt; - log the downloads.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;-l 0&lt;/code&gt; - remove recursion depth (which is 5 by default).&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;--wait=1h&lt;/code&gt; - be sneaky, download one file every hour.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;#27. Copy the arguments of the most recent command&lt;/h2&gt;
&lt;pre &gt;ALT + . (or ESC + .)&lt;/pre&gt;
&lt;p&gt;This keyboard shortcut works in shell's &lt;a href="http://www.catonmat.net/blog/bash-emacs-editing-mode-cheat-sheet/"&gt;emacs editing mode&lt;/a&gt; only, it copies the last argument form the last command to the current command. Here is an example:&lt;/p&gt;
&lt;pre &gt;
$ echo a b c
a b c

$ echo &amp;lt;Press ALT + .&gt;
$ echo c
&lt;/pre&gt;
&lt;p&gt;If you repeat the command, it copies the last argument from the command before the last, then if you repeat again, it copies the last argument from command before the command before the last, etc.&lt;/p&gt;
&lt;p&gt;Here is an example:&lt;/p&gt;
&lt;pre &gt;
$ echo 1 2 3
1 2 3
$ echo a b c
a b c

$ echo &amp;lt;Press ALT + .&gt;
$ echo c

$ echo &amp;lt;Press ALT + .&gt; again
$ echo 3
&lt;/pre&gt;
&lt;p&gt;However, if you wish to get 1st or 2nd or n-th argument, use the digit-argument command &lt;code&gt;ALT + 1 (or ESC + 1)&lt;/code&gt; or &lt;code&gt;ALT + 2 (or ESC +2)&lt;/code&gt;, etc. Here is an example:&lt;/p&gt;
&lt;pre &gt;
$ echo a b c
a b c

$ echo &amp;lt;Press ALT + 1&gt; &amp;lt;Press ALT + .&gt;
$ echo a
a

$ echo &amp;lt;Press ALT + 2&gt; &amp;lt;Press ALT + .&gt;
$ echo b
b
&lt;/pre&gt;
&lt;p&gt;See my article on &lt;a href="http://www.catonmat.net/blog/bash-emacs-editing-mode-cheat-sheet/"&gt;Emacs Editing Mode Keyboard Shortcuts&lt;/a&gt; for a tutorial and a cheat sheet of all the shortcuts.&lt;/p&gt;
&lt;h2&gt;#28. Execute a command without saving it in the history&lt;/h2&gt;
&lt;pre &gt;$ &amp;lt;space&gt;command&lt;/pre&gt;
&lt;p&gt;This one-liner works at least on bash, I haven't tested other shells.&lt;/p&gt;
&lt;p&gt;If you start your command by a space, it won't be saved to bash history (~/.bash_history file). This behavior is controlled by &lt;code&gt;$HISTIGNORE&lt;/code&gt; shell variable. Mine is set to &lt;code&gt;HISTIGNORE="&amp;:[ ]*"&lt;/code&gt;, which means don't save repeated commands to history, and don't save commands that start with a space to history. The values in &lt;code&gt;$HISTIGNORE&lt;/code&gt; are colon-separated.&lt;/p&gt;
&lt;p&gt;If you're interested, see my article "&lt;a href="http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/"&gt;The Definitive Guide to Bash Command Line History&lt;/a&gt;" for a short tutorial on how to work with shell history and a summary cheat sheet.&lt;/p&gt;
&lt;h2&gt;#29. Show the size of all sub folders in the current directory&lt;/h2&gt;
&lt;pre &gt;$ du -h --max-depth=1&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;--max-depth=1&lt;/code&gt; causes &lt;code&gt;du&lt;/code&gt; to summarize disk usage statistics for directories that are depth 1 from the current directory, that is, all directories in the current directory. The &lt;code&gt;-h&lt;/code&gt; argument makes the summary human-readable, that is, displays 5MB instead of 5242880 (bytes).&lt;/p&gt;
&lt;p&gt;If you are interested in both sub folder size and file size in the current directory, you can use the shorter:&lt;/p&gt;
&lt;pre &gt;$ du -sh *&lt;/pre&gt;
&lt;h2&gt;#30. Display the top ten running processes sorted by memory usage&lt;/h2&gt;
&lt;pre &gt;$ ps aux | sort -nk +4 | tail&lt;/pre&gt;
&lt;p&gt;This is certainly not the best way to display the top ten processes that consume the most memory, but, hey, it works.&lt;/p&gt;
&lt;p&gt;It takes the output of &lt;code&gt;ps aux&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;s it by 4th column numerically and then uses &lt;code&gt;tail&lt;/code&gt; to output the last then lines which happen to be the processes with the biggest memory consumption.&lt;/p&gt;
&lt;p&gt;If I was to find out who consumes the most memory, I'd simply use &lt;code&gt;htop&lt;/code&gt; or &lt;code&gt;top&lt;/code&gt; and not &lt;code&gt;ps&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Bonus one-liner: Start an SMTP server&lt;/h2&gt;
&lt;pre &gt;python -m smtpd -n -c DebuggingServer localhost:1025&lt;/pre&gt;
&lt;p&gt;This one-liner starts an SMTP server on port 1025. It uses Python's standard library &lt;code&gt;smtpd&lt;/code&gt; (specified by &lt;code&gt;-m smtpd&lt;/code&gt;) and passes it three arguments - &lt;code&gt;-n&lt;/code&gt;, &lt;code&gt;-c DebuggingServer&lt;/code&gt; and &lt;code&gt;localhost:1025&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-n&lt;/code&gt; argument tells Python not to setuid (change user) to "nobody" - it makes the code run under your user.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-c DebuggingServer&lt;/code&gt; argument tells Python to use &lt;code&gt;DebuggingServer&lt;/code&gt; class as the SMTP implementation that prints each message it receives to stdout.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;localhost:1025&lt;/code&gt; argument tells Python to start the SMTP server on locahost, port 1025.&lt;/p&gt;
&lt;p&gt;However, if you wish to start it on the standard port 25, you'll have to use &lt;code&gt;sudo&lt;/code&gt; command, because only root is allowed to start services on ports 1-1024. These are also known as privileged ports.&lt;/p&gt;
&lt;pre &gt;sudo python -m smtpd -n -c DebuggingServer localhost:25&lt;/pre&gt;
&lt;p&gt;This one-liner was coined by &lt;a href="http://evanculver.com/2010/03/18/handy-one-liners/"&gt;Evan Culver&lt;/a&gt;. Thanks to him!&lt;/p&gt;
&lt;h2&gt;That's it for today,&lt;/h2&gt;
&lt;p&gt;but be sure to come back the next time for "Yet Another Ten One-Liners from CommandLineFu Explained!"&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=u10fej7POxc:9KqBYA8sFpM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=u10fej7POxc:9KqBYA8sFpM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=u10fej7POxc:9KqBYA8sFpM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=u10fej7POxc:9KqBYA8sFpM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=u10fej7POxc:9KqBYA8sFpM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=u10fej7POxc:9KqBYA8sFpM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=u10fej7POxc:9KqBYA8sFpM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/u10fej7POxc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/another-ten-one-liners-from-commandlinefu-explained</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">A Real Turing Machine Running The Busy Beaver</title>
    <id>210</id>
    <updated>2010-03-29T09:45:37Z</updated>
    <published>2010-03-29T05:15:45Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/b1VVNTQ28Ao/a-real-turing-machine-running-the-busy-beaver" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/zOHVdWG8r_xU-LjLlDCp4-fBh_M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zOHVdWG8r_xU-LjLlDCp4-fBh_M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/zOHVdWG8r_xU-LjLlDCp4-fBh_M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/zOHVdWG8r_xU-LjLlDCp4-fBh_M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Remember my article on &lt;a href="http://www.catonmat.net/blog/busy-beaver/"&gt;The Busy Beaver Problem&lt;/a&gt;? Well, someone built a real Turing Machine and decided to run the busy beaver with 4 states on it. Here is the video.&lt;/p&gt;
&lt;div class="center-aligner"&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/2PjU6DJyBpw&amp;hl=en_US&amp;fs=1&amp;"&gt;&lt;/param&gt;
&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;
&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;
&lt;embed src="http://www.youtube.com/v/2PjU6DJyBpw&amp;hl=en_US&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;
&lt;/object&gt;
&lt;p&gt;Video URL: &lt;a href="http://www.youtube.com/watch?v=2PjU6DJyBpw"&gt;http://www.youtube.com/watch?v=2PjU6DJyBpw&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The Turing Machine in this video runs for 107 steps and halts with the total of 13 ones, as expected.&lt;/p&gt;
&lt;p&gt;In &lt;a href="http://www.catonmat.net/blog/busy-beaver/"&gt;my article on The Busy Beaver Problem&lt;/a&gt;, I also wrote a program that visualizes the tape changes. If you follow the video closely, you'll see that they match the visualization (black square stands for 1, white for 0).&lt;/p&gt;
&lt;div class="center-aligner"&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/blog/wp-content/uploads/2009/10/busy-beaver-four-states.png"&gt;&lt;br&gt;
&lt;small&gt;Tape changes for 4 state busy beaver.&lt;/small&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;See &lt;a href="http://aturingmachine.com"&gt;A Turing Machine&lt;/a&gt; website for more videos and information about how this machine was actually built. Also see &lt;a href="http://www.catonmat.net/blog/busy-beaver/"&gt;my article on Busy Beaver&lt;/a&gt; for a Turing Machine implementation in Python and C++.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=b1VVNTQ28Ao:n3qFmXUPhKE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=b1VVNTQ28Ao:n3qFmXUPhKE:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=b1VVNTQ28Ao:n3qFmXUPhKE:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=b1VVNTQ28Ao:n3qFmXUPhKE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=b1VVNTQ28Ao:n3qFmXUPhKE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=b1VVNTQ28Ao:n3qFmXUPhKE:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=b1VVNTQ28Ao:n3qFmXUPhKE:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/b1VVNTQ28Ao" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/a-real-turing-machine-running-the-busy-beaver</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">The Next Ten One-Liners from CommandLineFu Explained</title>
    <id>208</id>
    <updated>2010-04-30T11:53:56Z</updated>
    <published>2010-03-24T06:00:57Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/IbHTZFjHPU0/the-next-ten-one-liners-from-commandlinefu-explained" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hUS1DHkSuZZJAZn1E1Es_P9eG10/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hUS1DHkSuZZJAZn1E1Es_P9eG10/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hUS1DHkSuZZJAZn1E1Es_P9eG10/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hUS1DHkSuZZJAZn1E1Es_P9eG10/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.catonmat.net/blog/wp-content/uploads/2010/03/commandlinefu-explained.jpg" alt="CommandLineFu Explained" class="post-icon" align="left"&gt;Here are the next ten top one-liners from the &lt;a href="http://www.commandlinefu.com/"&gt;commandlinefu&lt;/a&gt; website. The &lt;a href="http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained/"&gt;first post&lt;/a&gt; about the topic became massively popular and received over 100,000 views in the first two days.&lt;/p&gt;
&lt;p&gt;Before I dive into the next ten one-liners, I want to take the chance and promote the other three article series on one-liners that I have written:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/awk-one-liners-explained-part-one/"&gt;Awk One-Liners Explained (4 part article).&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/sed-one-liners-explained-part-one/"&gt;Sed One-Liners Explained (3 part article).&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/perl-one-liners-explained-part-one/"&gt;Perl One-Liners Explained (9 part article, work in progress).&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://rus-linux.net/nlib.php?name=/MyLDP/consol/next_ten_oneliners.html"&gt;Russian translation now available.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Alright, so here are today's one-liners:&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#11. Edit the command you typed in your favorite editor&lt;/h2&gt;
&lt;pre &gt;$ command &amp;lt;CTRL-x CTRL-e&gt;&lt;/pre&gt;
&lt;p&gt;This one-liner opens the so-far typed &lt;code&gt;command&lt;/code&gt; in your favorite text editor for further editing. This is handy if you are typing a lengthier shell command. After you have done editing the command, quit from your editor successfully to execute it. To cancel execution, just erase it. If you quit unsuccessfully, the command you had typed before diving into the editor will be executed.&lt;/p&gt;
&lt;p&gt;Actually, I have to educate you, it's not a feature of the shell per se but a feature of the &lt;a href="http://tiswww.case.edu/php/chet/readline/rltop.html"&gt;readline library&lt;/a&gt; that most shells use for command line processing. This particular binding &lt;code&gt;CTRL-x CTRL-e&lt;/code&gt; only works in &lt;a href="http://www.catonmat.net/blog/bash-emacs-editing-mode-cheat-sheet/"&gt;readline emacs editing mode&lt;/a&gt;. The other mode is &lt;a href="http://www.catonmat.net/blog/bash-vi-editing-mode-cheat-sheet/"&gt;readline vi editing mode&lt;/a&gt;, in which the same can be accomplished by pressing &lt;code&gt;ESC&lt;/code&gt; and then &lt;code&gt;v&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The emacs editing mode is the default in all the shells that use the readline library. The usual command to change between the modes is &lt;code&gt;set -o vi&lt;/code&gt; to change to vi editing mode and &lt;code&gt;set -o emacs&lt;/code&gt; to change back to emacs editing mode.&lt;/p&gt;
&lt;p&gt;To change the editor, export the &lt;code&gt;$EDITOR&lt;/code&gt; shell variable to your preference. For example, to set the default editor to pico, type &lt;code&gt;export EDITOR=pico&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Another way to edit commands in a text editor is to use &lt;code&gt;fc&lt;/code&gt; shell builtin (at least bash has this builtin). The &lt;code&gt;fc&lt;/code&gt; command opens the previous edited command in your favorite text editor. It's easy to remember the &lt;code&gt;fc&lt;/code&gt; command because it stands for "&lt;strong&gt;f&lt;/strong&gt;ix &lt;strong&gt;c&lt;/strong&gt;ommand."&lt;/p&gt;
&lt;p&gt;Remember the &lt;code&gt;^foo^bar^&lt;/code&gt; command from the &lt;a href="http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained/"&gt;first top ten one-liners&lt;/a&gt;? You can emulate this behavior by typing &lt;code&gt;fc -s foo=bar&lt;/code&gt;. It will replace &lt;code&gt;foo&lt;/code&gt; with &lt;code&gt;bar&lt;/code&gt; in the previous command and execute it.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#12. Empty a file or create a new file&lt;/h2&gt;
&lt;pre &gt;$ &gt; file.txt&lt;/pre&gt;
&lt;p&gt;This one-liner either wipes the file called &lt;code&gt;file.txt&lt;/code&gt; empty or creates a new file called &lt;code&gt;file.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The shell first checks if the file &lt;code&gt;file.txt&lt;/code&gt; exists. If it does, the shell opens it and wipes it clean. If it doesn't exist, the shell creates the file and opens it. Next the shell proceeds to redirecting standard output to the opened file descriptor. Since there is nothing on the standard output, the command succeeds, closes the file descriptor, leaving the file empty.&lt;/p&gt;
&lt;p&gt;Creating a new empty file is also called &lt;em&gt;touching&lt;/em&gt; and can be done by &lt;code&gt;$ touch file.txt&lt;/code&gt; command. The &lt;code&gt;touch&lt;/code&gt; command can also be used for changing timestamps of the commands. Touch, however, won't wipe the file clean, it will only change the access and modification timestamps to the current time.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#13. Create a tunnel from localhost:2001 to somemachine:80&lt;/h2&gt;
&lt;pre &gt;$ ssh -N -L2001:localhost:80 somemachine&lt;/pre&gt;
&lt;p&gt;This one-liner creates a tunnel from your computer's port 2001 to somemachine's port 80. Each time you connect to port 2001 on your machine, your connection gets tunneled to somemachine:80.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-L&lt;/code&gt; option can be summarized as &lt;code&gt;-L port:host:hostport&lt;/code&gt;. Whenever a connection is made to &lt;code&gt;localhost:port&lt;/code&gt;, the connection is forwarded over the secure channel, and a connection is made to &lt;code&gt;host:hostport&lt;/code&gt; from the remote machine.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-N&lt;/code&gt; option makes sure you don't run shell as you connect to somemachine.&lt;/p&gt;
&lt;p&gt;To make things more concrete, here is another example:&lt;/p&gt;
&lt;pre &gt;$ ssh -f -N -L2001:www.google.com:80 somemachine&lt;/pre&gt;
&lt;p&gt;This one-liner creates a tunnel from your computer's port 2001 to www.google.com:80 via somemachine. Each time you connect to localhost:2001, ssh tunnels your request via somemachine, where it tries to open a connection to www.google.com.&lt;/p&gt;
&lt;p&gt;Notice the additional &lt;code&gt;-f&lt;/code&gt; flag - it makes ssh daemonize (go into background) so it didn't consume a terminal.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#14. Reset terminal&lt;/h2&gt;
&lt;pre &gt;$ reset&lt;/pre&gt;
&lt;p&gt;This command resets the terminal. You know, when you have accidentally output binary data to the console, it becomes messed up. The &lt;code&gt;reset&lt;/code&gt; command usually cleans it up. It does that by sending a bunch of special byte sequences to the terminal. The terminal interprets them as special commands and executes them.&lt;/p&gt;
&lt;p&gt;Here is what BusyBox's &lt;code&gt;reset&lt;/code&gt; command does:&lt;/p&gt;
&lt;pre &gt;printf("\033c\033(K\033[J\033[0m\033[?25h");&lt;/pre&gt;
&lt;p&gt;It sends a bunch of escape codes and a bunch of CSI commands. Here is what they mean:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;code&gt;\033c&lt;/code&gt;: "ESC c" - sends reset to the terminal.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;\033(K&lt;/code&gt;: "ESC ( K" - reloads the screen output mapping table.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;\033[J&lt;/code&gt;: "ESC [ J" - erases display.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;\033[0m&lt;/code&gt;: "ESC [ 0 m" - resets all display attributes to their defaults.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;\033[?25h&lt;/code&gt;: "ESC [ ? 25 h" - makes cursor visible.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#15. Tweet from the shell&lt;/h2&gt;
&lt;pre &gt;$ curl -u user:pass -d status='Tweeting from the shell' http://twitter.com/statuses/update.xml&lt;/pre&gt;
&lt;p&gt;This one-liner tweets your message from the terminal. It uses the &lt;a href="http://curl.haxx.se/"&gt;curl&lt;/a&gt; program to HTTP POST your tweet via &lt;a href="http://apiwiki.twitter.com/Twitter-REST-API-Method%3A-statuses%C2%A0update"&gt;Twitter's API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-u user:pass&lt;/code&gt; argument sets the login and password to use for authentication. If you don't wish your password to be saved in the shell history, omit the &lt;code&gt;:pass&lt;/code&gt; part and curl will prompt you for the password as it tries to authenticate. Oh, and while we are at shell history, another way to omit password from being saved in the history is to start the command with a space! For example, &lt;code&gt;&amp;lt;space&gt;curl ...&lt;/code&gt; won't save the curl command to the shell history.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-d status='...'&lt;/code&gt; instructs curl to use the HTTP POST method for the request and send &lt;code&gt;status=...&lt;/code&gt; as POST data.&lt;/p&gt;
&lt;p&gt;Finally, &lt;code&gt;http://twitter.com/statuses/update.xml&lt;/code&gt; is the API URL to POST the data to.&lt;/p&gt;
&lt;p&gt;Talking about Twitter, I'd love if you &lt;a href="http://twitter.com/pkrumins"&gt;followed me on Twitter!&lt;/a&gt; :)&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#16. Execute a command at midnight&lt;/h2&gt;
&lt;pre &gt;$ echo cmd | at midnight&lt;/pre&gt;
&lt;p&gt;This one-liner sends the shell command &lt;code&gt;cmd&lt;/code&gt; to the at-daemon (atd) for execution at midnight.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;at&lt;/code&gt; command is light on the execution-time argument, you may write things like &lt;code&gt;4pm tomorrow&lt;/code&gt; to execute it at 4pm tomorrow, &lt;code&gt;9pm next year&lt;/code&gt; to run it on the same date at 9pm the next year, &lt;code&gt;6pm + 10 days&lt;/code&gt; to run it at 6pm after 10 days, or &lt;code&gt;now +1minute&lt;/code&gt; to run it after a minute.&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;atq&lt;/code&gt; command to list all the jobs that are scheduled for execution and &lt;code&gt;atrm&lt;/code&gt; to remove a job from the queue.&lt;/p&gt;
&lt;p&gt;Compared to the universally known &lt;code&gt;cron&lt;/code&gt;, &lt;code&gt;at&lt;/code&gt; is suitable for one-time jobs. For example, you'd use &lt;code&gt;cron&lt;/code&gt; to execute a job every day at midnight but you would use &lt;code&gt;at&lt;/code&gt; to execute a job only today at midnight.&lt;/p&gt;
&lt;p&gt;Also be aware that if the load is greater than some number (for one processor systems the default is 0.8), then &lt;code&gt;atd&lt;/code&gt; &lt;strong&gt;will not&lt;/strong&gt; execute the command! That can be fixed by specifying a greater max load to &lt;code&gt;atd&lt;/code&gt; via &lt;code&gt;-l&lt;/code&gt; argument.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#17. Output your microphone to other computer's speaker&lt;/h2&gt;
&lt;pre &gt;$ dd if=/dev/dsp | ssh username@host dd of=/dev/dsp&lt;/pre&gt;
&lt;p&gt;The default sound device on Linux is &lt;code&gt;/dev/dsp&lt;/code&gt;. It can be both written to and read from. If it's read from then the audio subsystem will read the data from the microphone. If it's written to, it will send audio to your speaker.&lt;/p&gt;
&lt;p&gt;This one-liner reads audio from your microphone via the &lt;code&gt;dd if=/dev/dsp&lt;/code&gt; command (&lt;code&gt;if&lt;/code&gt; stands for input file) and pipes it as standard input to &lt;code&gt;ssh&lt;/code&gt;. &lt;code&gt;Ssh&lt;/code&gt;, in turn, opens a connection to a computer at &lt;code&gt;host&lt;/code&gt; and runs the &lt;code&gt;dd of=/dev/dsp&lt;/code&gt; (&lt;code&gt;of&lt;/code&gt; stands for output file) on it. &lt;code&gt;Dd of=/dev/dsp&lt;/code&gt; receives the standard input that &lt;code&gt;ssh&lt;/code&gt; received from &lt;code&gt;dd if=/dev/dsp&lt;/code&gt;. The result is that your microphone gets output on &lt;code&gt;host&lt;/code&gt; computer's speaker.&lt;/p&gt;
&lt;p&gt;Want to scare your colleague? Dump &lt;code&gt;/dev/urandom&lt;/code&gt; to his speaker by &lt;code&gt;dd if=/dev/urandom&lt;/code&gt;.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#18. Create and mount a temporary RAM partition&lt;/h2&gt;
&lt;pre &gt;# mount -t tmpfs -o size=1024m tmpfs /mnt &lt;/pre&gt;
&lt;p&gt;This command creates a temporary RAM filesystem of 1GB (1024m) and mounts it at &lt;code&gt;/mnt&lt;/code&gt;. The &lt;code&gt;-t&lt;/code&gt; flag to mount specifies the filesystem type and the &lt;code&gt;-o size=1024m&lt;/code&gt; passes the &lt;code&gt;size&lt;/code&gt; sets the filesystem size.&lt;/p&gt;
&lt;p&gt;If it doesn't work, make sure your kernel was compiled to support the tmpfs. If tmpfs was compiled as a module, make sure to load it via &lt;code&gt;modprobe tmpfs&lt;/code&gt;. If it still doesn't work, you'll have to recompile your kernel.&lt;/p&gt;
&lt;p&gt;To unmount the ram disk, use the &lt;code&gt;umount /mnt&lt;/code&gt; command (as root). But remember that mounting at &lt;code&gt;/mnt&lt;/code&gt; is not the best practice. Better mount your drive to &lt;code&gt;/mnt/tmpfs&lt;/code&gt; or a similar path.&lt;/p&gt;
&lt;p&gt;If you wish your filesystem to grow dynamically, use &lt;code&gt;ramfs&lt;/code&gt; filesystem type instead of &lt;code&gt;tmpfs&lt;/code&gt;. Another note: tmpfs may use swap, while ramfs won't.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#19. Compare a remote file with a local file&lt;/h2&gt;
&lt;pre &gt;$ ssh user@host cat /path/to/remotefile | diff /path/to/localfile -&lt;/pre&gt;
&lt;p&gt;This one-liner diffs the file &lt;code&gt;/path/to/localfile&lt;/code&gt; on local machine with a file &lt;code&gt;/path/to/remotefile&lt;/code&gt; on &lt;code&gt;host&lt;/code&gt; machine.&lt;/p&gt;
&lt;p&gt;It first opens a connection via &lt;code&gt;ssh&lt;/code&gt; to &lt;code&gt;host&lt;/code&gt; and executes the &lt;code&gt;cat /path/to/remotefile&lt;/code&gt; command there. The shell then takes the output and pipes it to &lt;code&gt;diff /path/to/localfile -&lt;/code&gt; command. The second argument &lt;code&gt;-&lt;/code&gt; to &lt;code&gt;diff&lt;/code&gt; tells it to diff the file &lt;code&gt;/path/to/localfile&lt;/code&gt; against standard input. That's it.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#20. Find out which programs listen on which TCP ports&lt;/h2&gt;
&lt;pre &gt;# netstat -tlnp&lt;/pre&gt;
&lt;p&gt;This is an easy one. Netstat is the standard utility for listing information about Linux networking subsystem. In this particular one-liner it's called with &lt;code&gt;-tlnp&lt;/code&gt; arguments:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;code&gt;-t&lt;/code&gt; causes netstat to only list information about TCP sockets.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-l&lt;/code&gt; causes netstat to only list information about listening sockets.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-n&lt;/code&gt; causes netstat not to do reverse lookups on the IPs.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-p&lt;/code&gt; causes netstat to print the PID and name of the program to which the socket belongs (requires root).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To find more detailed info about open sockets on your computer, use the &lt;code&gt;lsof&lt;/code&gt; utility. See my article "&lt;a href="http://www.catonmat.net/blog/unix-utilities-lsof/"&gt;A Unix Utility You Should Know About: lsof&lt;/a&gt;" for more information.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;That's it for today.&lt;/h2&gt;
&lt;p&gt;Tune in the next time for "Another Ten One-Liners from CommandLineFu Explained". There are many more nifty commands to write about. But for now, have fun and see ya!&lt;/p&gt;
&lt;p&gt;PS. &lt;a href="http://twitter.com/pkrumins"&gt;Follow me on twitter for updates!&lt;/a&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=IbHTZFjHPU0:9MTdrOISR2E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=IbHTZFjHPU0:9MTdrOISR2E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=IbHTZFjHPU0:9MTdrOISR2E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=IbHTZFjHPU0:9MTdrOISR2E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=IbHTZFjHPU0:9MTdrOISR2E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=IbHTZFjHPU0:9MTdrOISR2E:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=IbHTZFjHPU0:9MTdrOISR2E:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/IbHTZFjHPU0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/the-next-ten-one-liners-from-commandlinefu-explained</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Top Ten One-Liners from CommandLineFu Explained</title>
    <id>195</id>
    <updated>2010-06-01T18:44:19Z</updated>
    <published>2010-03-18T03:00:21Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/crt1jT0uPnU/top-ten-one-liners-from-commandlinefu-explained" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nDPPaKjYg_gA95NUZVoYFwmKEwI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nDPPaKjYg_gA95NUZVoYFwmKEwI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nDPPaKjYg_gA95NUZVoYFwmKEwI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nDPPaKjYg_gA95NUZVoYFwmKEwI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2010/03/commandlinefu-explained.jpg' alt='CommandLineFu Explained' class="post-icon" align="left"&gt;I love working in the shell. Mastery of shell lets you get things done in seconds, rather than minutes or hours, if you chose to write a program instead. &lt;/p&gt;
&lt;p&gt;In this article I'd like to explain the &lt;a href="http://www.commandlinefu.com/commands/browse/sort-by-votes"&gt;top one-liners&lt;/a&gt; from the &lt;a href="http://www.commandlinefu.com"&gt;commandlinefu.com&lt;/a&gt;. It's a user-driven website where people get to choose the best and most useful shell one-liners.&lt;/p&gt;
&lt;p&gt;But before I do that, I want to take the opportunity and link to a few of my articles that I wrote some time ago on working efficiently in the command line:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/bash-vi-editing-mode-cheat-sheet/"&gt;Working Efficiently in Bash (Part I).&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/bash-emacs-editing-mode-cheat-sheet/"&gt;Working Efficiently in Bash (Part II).&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/"&gt;The Definitive Guide to Bash Command Line History.&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/set-operations-in-unix-shell/"&gt;A fun article on Set Operations in the Shell.&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/solving-google-treasure-hunt-prime-number-problem-four/"&gt;Another fun article on Solving Google Treasure Hunt in the Shell.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://rus-linux.net/nlib.php?name=/MyLDP/consol/oneliners.html"&gt;Russian translation now available.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And now the explanation of top one-liners from commandlinefu.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#1. Run the last command as root&lt;/h2&gt;
&lt;pre &gt;$ sudo !!&lt;/pre&gt;
&lt;p&gt;We all know what the &lt;code&gt;sudo&lt;/code&gt; command does - it runs the command as another user, in this case, it runs the command as superuser because no other user was specified. But what's really interesting is the bang-bang &lt;code&gt;!!&lt;/code&gt; part of the command. It's called the &lt;strong&gt;event designator&lt;/strong&gt;. An event designator references a command in shell's history. In this case the event designator references the previous command. Writing &lt;code&gt;!!&lt;/code&gt; is the same as writing &lt;code&gt;!-1&lt;/code&gt;. The &lt;code&gt;-1&lt;/code&gt; refers to the last command. You can generalize it, and write &lt;code&gt;!-n&lt;/code&gt; to refer to the n-th previous command. To view all your previous commands, type &lt;code&gt;history&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This one-liner is actually really bash-specific, as event designators are a feature of bash.&lt;/p&gt;
&lt;p&gt;I wrote about event designators in much more detail in my article "&lt;a href="http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/"&gt;The Definitive Guide to Bash Command Line History&lt;/a&gt;." The article also comes with a printable cheat sheet for working with the history.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#2. Serve the current directory at http://localhost:8000/&lt;/h2&gt;
&lt;pre &gt;$ python -m SimpleHTTPServer&lt;/pre&gt;
&lt;p&gt;This one-liner starts a web server on port 8000 with the contents of current directory on all the interfaces (address 0.0.0.0), not just localhost. If you have "&lt;code&gt;index.html&lt;/code&gt;" or "&lt;code&gt;index.htm&lt;/code&gt;" files, it will serve those, otherwise it will list the contents of the currently working directory.&lt;/p&gt;
&lt;p&gt;It works because python comes with a standard module called &lt;code&gt;SimpleHTTPServer&lt;/code&gt;. The &lt;code&gt;-m&lt;/code&gt; argument makes python to search for a module named &lt;code&gt;SimpleHTTPServer.py&lt;/code&gt; in all the possible system locations (listed in &lt;code&gt;sys.path&lt;/code&gt; and &lt;code&gt;$PYTHONPATH&lt;/code&gt; shell variable). Once found, it executes it as a script. If you look at the source code of this module, you'll find that this module tests if it's run as a script &lt;code&gt;if __name__ == '__main__'&lt;/code&gt;, and if it is, it runs the &lt;code&gt;test()&lt;/code&gt; method that makes it run a web server in the current directory.&lt;/p&gt;
&lt;p&gt;To use a different port, specify it as the next argument:&lt;/p&gt;
&lt;pre &gt;$ python -m SimpleHTTPServer 8080&lt;/pre&gt;
&lt;p&gt;This command runs a HTTP server on all local interfaces on port 8080.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#3. Save a file you edited in vim without the needed permissions&lt;/h2&gt;
&lt;pre &gt;:w !sudo tee %&lt;/pre&gt;
&lt;p&gt;This happens to me way too often. I open a system config file in vim and edit it just to find out that I don't have permissions to save it. This one-liner saves the day. Instead of writing the while to a temporary file &lt;code&gt;:w /tmp/foobar&lt;/code&gt; and then moving the temporary file to the right destination &lt;code&gt;mv /tmp/foobar /etc/service.conf&lt;/code&gt;, you now just type the one-liner above in vim and it will save the file.&lt;/p&gt;
&lt;p&gt;Here is how it works, if you look at the vim documentation (by typing &lt;code&gt;:he :w&lt;/code&gt; in vim), you'll find the reference to the command &lt;code&gt;:w !{cmd}&lt;/code&gt; that says that vim runs &lt;code&gt;{cmd}&lt;/code&gt; and passes it the contents of the file as standard input. In this one-liner the &lt;code&gt;{cmd}&lt;/code&gt; part is the &lt;code&gt;sudo tee %&lt;/code&gt; command. It runs &lt;code&gt;tee %&lt;/code&gt; as superuser. But wait, what is &lt;code&gt;%&lt;/code&gt;? Well, it's a read-only register in vim that contains the filename of the current file! Therefore the command that vim executes becomes &lt;code&gt;tee current_filename&lt;/code&gt;, with the current directory being whatever the &lt;code&gt;current_file&lt;/code&gt; is in. Now what does &lt;code&gt;tee&lt;/code&gt; do? The &lt;code&gt;tee&lt;/code&gt; command takes standard input and write it to a file! Rephrasing, it takes the contents of the file edited in vim, and writes it to the file (while being root)! All done!&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#4. Change to the previous working directory&lt;/h2&gt;
&lt;pre &gt;$ cd -&lt;/pre&gt;
&lt;p&gt;Everyone knows this, right? The dash "&lt;code&gt;-&lt;/code&gt;" is short for "previous working directory." The previous working directory is defined by &lt;code&gt;$OLDPWD&lt;/code&gt; shell variable. After you use the &lt;code&gt;cd&lt;/code&gt; command, it sets the &lt;code&gt;$OLDPWD&lt;/code&gt; environment variable, and then, if you type the short version &lt;code&gt;cd -&lt;/code&gt;, it effectively becomes &lt;code&gt;cd $OLDPWD&lt;/code&gt; and changes to the previous directory.&lt;/p&gt;
&lt;p&gt;To change to a directory named "&lt;code&gt;-&lt;/code&gt;", you have to either cd to the parent directory and then do &lt;code&gt;cd ./-&lt;/code&gt; or do &lt;code&gt;cd /full/path/to/-&lt;/code&gt;.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#5. Run the previous shell command but replace string "foo" with "bar"&lt;/h2&gt;
&lt;pre &gt;$ ^foo^bar^&lt;/pre&gt;
&lt;p&gt;This is another event designator. This one is for quick substitution. It replaces &lt;code&gt;foo&lt;/code&gt; with &lt;code&gt;bar&lt;/code&gt; and repeats the last command. It's actually a shortcut for &lt;code&gt;!!:s/foo/bar/&lt;/code&gt;. This one-liner applies the &lt;code&gt;s&lt;/code&gt; modifier to the &lt;code&gt;!!&lt;/code&gt; event designator. As we learned from one-liner #1, the &lt;code&gt;!!&lt;/code&gt; event designator stands for the previous command. Now the &lt;code&gt;s&lt;/code&gt; modifier stands for substitute (greetings to &lt;a href="http://www.catonmat.net/blog/sed-one-liners-explained-part-one/"&gt;sed&lt;/a&gt;) and it substitutes the first word with the second word.&lt;/p&gt;
&lt;p&gt;Note that this one-liner replaces just the first word in the previous command. To replace all words, add the &lt;code&gt;g&lt;/code&gt; modifer (&lt;code&gt;g&lt;/code&gt; for global):&lt;/p&gt;
&lt;pre &gt;$ !!:gs/foo/bar&lt;/pre&gt;
&lt;p&gt;This one-liner is also bash-specific, as event designators are a feature of bash.&lt;/p&gt;
&lt;p&gt;Again, see my article "&lt;a href="http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/"&gt;The Definitive Guide to Bash Command Line History&lt;/a&gt;." I explain all this stuff in great detail.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#6. Quickly backup or copy a file&lt;/h2&gt;
&lt;pre &gt;$ cp filename{,.bak}&lt;/pre&gt;
&lt;p&gt;This one-liner copies the file named &lt;code&gt;filename&lt;/code&gt; to a file named &lt;code&gt;filename.bak&lt;/code&gt;. Here is how it works. It uses &lt;strong&gt;brace expansion&lt;/strong&gt; to construct a list of arguments for the &lt;code&gt;cp&lt;/code&gt; command. Brace expansion is a mechanism by which arbitrary strings may be generated. In this one-liner &lt;code&gt;filename{,.bak}&lt;/code&gt; gets brace expanded to &lt;code&gt;filename filename.bak&lt;/code&gt; and puts in place of the brace expression. The command becomes &lt;code&gt;cp filename filename.bak&lt;/code&gt; and file gets copied.&lt;/p&gt;
&lt;p&gt;Talking more about brace expansion, you can do all kinds of combinatorics with it. Here is a fun application:&lt;/p&gt;
&lt;pre &gt;$ echo {a,b,c}{a,b,c}{a,b,c}&lt;/pre&gt;
&lt;p&gt;It generates all the possible strings 3-letter from the set &lt;code&gt;{a, b, c}&lt;/code&gt;:&lt;/p&gt;
&lt;pre &gt;
aaa aab aac aba abb abc aca acb acc
baa bab bac bba bbb bbc bca bcb bcc
caa cab cac cba cbb cbc cca ccb ccc
&lt;/pre&gt;
&lt;p&gt;And here is how to generate all the possible 2-letter strings from the set of &lt;code&gt;{a, b, c}&lt;/code&gt;:&lt;/p&gt;
&lt;pre &gt;
$ echo {a,b,c}{a,b,c}
&lt;/pre&gt;
&lt;p&gt;It produces:&lt;/p&gt;
&lt;pre &gt;
aa ab ac ba bb bc ca cb cc
&lt;/pre&gt;
&lt;p&gt;If you liked this, you may also like my article where I defined a bunch of set operations (such as intersection, union, symmetry, powerset, etc) by using just shell commands. The article is called "&lt;a href="http://www.catonmat.net/blog/set-operations-in-unix-shell/"&gt;Set Operations in the Unix Shell&lt;/a&gt;." (And since I have sets in the shell, I will soon write articles on on "&lt;strong&gt;Combinatorics in the Shell&lt;/strong&gt;" and "&lt;strong&gt;Algebra in the Shell&lt;/strong&gt;". Fun topics to explore. Perhaps even "Topology in the Shell" :))&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#7. mtr - traceroute and ping combined&lt;/h2&gt;
&lt;pre &gt;$ mtr google.com&lt;/pre&gt;
&lt;p&gt;MTR, bettern known as "Matt's Traceroute" combines both &lt;code&gt;traceroute&lt;/code&gt; and &lt;code&gt;ping&lt;/code&gt; command. After each successful hop, it sends a ping request to the found machine, this way it produces output of both &lt;code&gt;traceroute&lt;/code&gt; and &lt;code&gt;ping&lt;/code&gt; to better understand the quality of link. If it finds out a packet took an alternative route, it displays it, and by default it keeps updating the statistics so you knew what was going on in real time.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#8. Find the last command that begins with "whatever," but avoid running it&lt;/h2&gt;
&lt;pre &gt;$ !whatever:p&lt;/pre&gt;
&lt;p&gt;Another use of event designators. The &lt;code&gt;!whatever&lt;/code&gt; designator searches the shell history for the most recently executed command that starts with &lt;code&gt;whatever&lt;/code&gt;. But instead of executing it, it prints it. The &lt;code&gt;:p&lt;/code&gt; modifier makes it print instead of executing.&lt;/p&gt;
&lt;p&gt;This one-liner is bash-specific, as event designators are a feature of bash.&lt;/p&gt;
&lt;p&gt;Once again, see my article "&lt;a href="http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history/"&gt;The Definitive Guide to Bash Command Line History&lt;/a&gt;." I explain all this stuff in great detail.&lt;/p&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#9. Copy your public-key to remote-machine for public-key authentication&lt;/h2&gt;
&lt;pre &gt;$ ssh-copy-id remote-machine&lt;/pre&gt;
&lt;p&gt;This one-liner copies your public-key, that you generated with &lt;code&gt;ssh-keygen&lt;/code&gt; (either SSHv1 file identity.pub or SSHv2 file id_rsa.pub) to the &lt;code&gt;remote-machine&lt;/code&gt; and places it in &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file. This ensures that the next time you try to log into that machine, public-key authentication (commonly referred to as "passwordless authentication.") will be used instead of the regular password authentication.&lt;/p&gt;
&lt;p&gt;If you wished to do it yourself, you'd have to take the following steps:&lt;/p&gt;
&lt;pre &gt;
your-machine$ scp ~/.ssh/identity.pub remote-machine:
your-machine$ ssh remote-machine
remote-machine$ cat identity.pub &gt;&gt; ~/.ssh/authorized_keys
&lt;/pre&gt;
&lt;p&gt;This one-liner saves a great deal of typing. Actually I just found out that there was a shorter way to do it:&lt;/p&gt;
&lt;pre &gt;
your-machine$ ssh remote-machine 'cat &gt;&gt; .ssh/authorized_keys' &amp;lt; .ssh/identity.pub
&lt;/pre&gt;
&lt;h2 style="margin-bottom: 10px"&gt;#10. Capture video of a linux desktop&lt;/h2&gt;
&lt;pre &gt;$ ffmpeg -f x11grab -s wxga -r 25 -i :0.0 -sameq /tmp/out.mpg&lt;/pre&gt;
&lt;p&gt;A pure coincidence, I have done so much video processing with ffmpeg that I know what most of this command does without looking much in the manual.&lt;/p&gt;
&lt;p&gt;The ffmpeg generally can be descibed as a command that takes a bunch of options and the last option is the output file. In this case the options are &lt;code&gt;-f x11grab -s wxga -r 25 -i :0.0 -sameq&lt;/code&gt; and the output file is &lt;code&gt;/tmp/out.mpg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is what the options mean:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;code&gt;-f x11grab&lt;/code&gt; makes ffmpeg to set the input video format as x11grab. The X11 framebuffer has a specific format it presents data in and it makes ffmpeg to decode it correctly.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-s wxga&lt;/code&gt; makes ffmpeg to set the size of the video to wxga which is shortcut for 1366x768. This is a strange resolution to use, I'd just write &lt;code&gt;-s 800x600&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-r 25&lt;/code&gt; sets the framerate of the video to 25fps.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-i :0.0&lt;/code&gt; sets the video input file to X11 display 0.0 at localhost.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;-sameq&lt;/code&gt; preserves the quality of input stream. It's best to preserve the quality and post-process it later.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also specify ffmpeg to grab display from another x-server by changing the &lt;code&gt;-i :0.0&lt;/code&gt; to &lt;code&gt;-i host:0.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you're interested in ffmpeg, here are my other articles on ffmpeg that I wrote while ago:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/how-to-extract-audio-tracks-from-youtube-videos/"&gt;How to Extract Audio Tracks from YouTube Videos&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/converting-youtube-flvs-to-a-better-format-with-ffmpeg/"&gt;Converting YouTube Flash Videos to a Better Format with ffmpeg&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PS. This article was so fun to write, that I decided to write several more parts. Tune in the next time for "The Next Top Ten One-Liners from CommandLineFu Explained" :)&lt;/p&gt;
&lt;p&gt;Have fun. See ya!&lt;/p&gt;
&lt;p&gt;PSS. &lt;a href="http://twitter.com/pkrumins"&gt;Follow me on twitter for updates&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This article was sponsored by:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt; &lt;li&gt;&lt;a href="http://www.netfirms.ca/"&gt;Canadian domain names&lt;/a&gt; available through Netfirms.ca&lt;/li&gt;
 &lt;li&gt;Hosting.com offers &lt;a href="http://www.hosting.com/dedicatedservershosting/"&gt;Dedicated server hosting&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;Advanceware's &lt;a href="http://www.advanceware.net/"&gt;Inventory management software&lt;/a&gt; can help you organize your resources.&lt;/li&gt;
 &lt;li&gt;Sherweb provides &lt;a href="http://www.sherweb.com/hosted-exchange"&gt;Hosted Exchange&lt;/a&gt; solutions for your small business.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://www.catonmat.net/feedback/?subject=Interested+in+Sponsoring+Articles"&gt;Contact me&lt;/a&gt;, if you wish to sponsor any other of my existing posts or future posts!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=crt1jT0uPnU:kKpCadsN08A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=crt1jT0uPnU:kKpCadsN08A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=crt1jT0uPnU:kKpCadsN08A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=crt1jT0uPnU:kKpCadsN08A:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=crt1jT0uPnU:kKpCadsN08A:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=crt1jT0uPnU:kKpCadsN08A:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=crt1jT0uPnU:kKpCadsN08A:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/crt1jT0uPnU" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/top-ten-one-liners-from-commandlinefu-explained</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Visual Math Friday</title>
    <id>206</id>
    <updated>2010-03-05T15:58:12Z</updated>
    <published>2010-03-05T08:00:02Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/UKtOfIravfs/visual-math-friday" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rScxpD2qbWV5V1hTl71nnnRqQeU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rScxpD2qbWV5V1hTl71nnnRqQeU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rScxpD2qbWV5V1hTl71nnnRqQeU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rScxpD2qbWV5V1hTl71nnnRqQeU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2010/03/visual-math-friday.gif' alt='Visual Math Friday' class="post-icon" align="left" /&gt;Hey everyone, I'm starting a new article series here on catonmat that will be published on Fridays. It's called "&lt;strong&gt;Visual Math Friday&lt;/strong&gt;." The goal of this article series is to assemble all the wonderful mathematical proofs and identities that can be proven in a single picture or drawing. I have been collecting them for years from various books, math journals, websites and video lectures and have collected several hundred of them.&lt;/p&gt;
&lt;p&gt;If you have been following my blog, you'll have noticed that I love to explain things. I'll use the same writing style in this series as well. I'll post the visual proof together with my explanation. In the explanations I'll walk you through the proof, suggesting how to think about the visual image. But it's best if you try to understand the proof without reading my explanation and only then read it.&lt;/p&gt;
&lt;p&gt;The proofs come from algebra, number theory, geometry, calculus, complex analysis, topology and various other fields of mathematics. I'll do one proof a week and will try to alternate between really easy, moderate and difficult proofs every week so that readers with various mathematical backgrounds can enjoy the series.&lt;/p&gt;
&lt;p&gt;I'll start with a really easy integer sum proof this week. Without further ado, here it is.&lt;/p&gt;
&lt;div class="center-aligner" style="padding: 10px 0"&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2010/03/visual-math-proof-1-3-5-7-9-11-13-n2.gif' alt='1 + 3 + 5 + 7 + 9 + 11 + 13 + … = n²' /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now try to figure what it proves without reading further! The colors play an important role in the visual proofs, as do the shape of the visual drawing, the shapes on it and their arrangement!&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;The Proof&lt;/h2&gt;
&lt;p&gt;This picture proves that the sum of first n odd numbers is equal to n². In other words:&lt;/p&gt;
&lt;div class="center-aligner"&gt;&lt;p&gt;1 + 3 + 5 + 7 + 9 + 11 + ... + (2n-1) = n².&lt;/p&gt;
&lt;/div&gt;
&lt;h2 style="margin-bottom:10px"&gt;Explanation&lt;/h2&gt;
&lt;p&gt;Imagine that the blue and green dots are marbles. Now let's look at the lower left corner. One blue marble is located there. Next if we follow the diagonal to the upper right corner, we see that the &lt;span style="color:#2a4ccb; font-weight: bold"&gt;1&lt;/span&gt; blue marble is kind-of wrapped in &lt;span style="color:#56d932; font-weight: bold"&gt;3&lt;/span&gt; green marbles, then they in turn are wrapped in &lt;span style="color:#2a4ccb; font-weight: bold"&gt;5&lt;/span&gt; blue marbles again, then those are wrapped in &lt;span style="color:#56d932; font-weight: bold"&gt;7&lt;/span&gt; green ones, which in turn are wrapped in &lt;span style="color:#2a4ccb; font-weight: bold"&gt;9&lt;/span&gt; blue ones, then &lt;span style="color:#56d932; font-weight: bold"&gt;11&lt;/span&gt; green ones, and finally &lt;span style="color:#2a4ccb; font-weight: bold"&gt;13&lt;/span&gt; ones.&lt;/p&gt;
&lt;p&gt;This suggests that we could look at the sum &lt;span style="color:#2a4ccb; font-weight: bold"&gt;1&lt;/span&gt; + &lt;span style="color:#56d932; font-weight: bold"&gt;3&lt;/span&gt; + &lt;span style="color:#2a4ccb; font-weight: bold"&gt;5&lt;/span&gt; + &lt;span style="color:#56d932; font-weight: bold"&gt;7&lt;/span&gt; + &lt;span style="color:#2a4ccb; font-weight: bold"&gt;9&lt;/span&gt; + &lt;span style="color:#56d932; font-weight: bold"&gt;11&lt;/span&gt; + &lt;span style="color:#2a4ccb; font-weight: bold"&gt;13&lt;/span&gt;. Well what is it? It's 49. Also what does this sum involve? It involves only odd numbers. Interesting.&lt;/p&gt;
&lt;p&gt;Now let's count how many marbles we have on each side. 7 on one side and 7 on the other. And what is 7x7? It's 49! And how many numbers did we sum together? Well, seven - 1, 3, 5, 7, 9, 11, 13. Interesting.&lt;/p&gt;
&lt;p&gt;Could it be that the sum of the first n odd numbers is equal to n²? Or in other words, is 1 + 3 + 5 + 7 + ... + (2n-1) equal to n²?&lt;/p&gt;
&lt;p&gt;Let's try to prove this hypothesis by going one number further and adding 15 green marbles - 13 filled marbles and 2 semi-filled marbles:&lt;/p&gt;
&lt;div class="center-aligner" style="padding: 10px 0"&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2010/03/visual-math-proof-1-3-5-7-9-11-13-15-n2.gif' alt='Visual Math Proof - sum of odd numbers is n squared' /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Adding 15 marbles created a square of marbles again - now we have 64 marbles, 8 on each side.&lt;/p&gt;
&lt;p&gt;The 2 semi-filled marbles are very important here. Each time we go further from n odd marbles to n+1 odd marbles, the difference changes by 2. This difference of two marbles can always be put where the semi-filled ones are in this picture.&lt;/p&gt;
&lt;p&gt;This actually concludes the proof. We showed that the proof worked for several marbles, and showed how it still works if we went one step further. Therefore it works for all future steps. This method of proof is called &lt;a href="http://en.wikipedia.org/wiki/Mathematical_induction"&gt;mathematical induction&lt;/a&gt; and it's a very powerful and important tool in mathematics for proving sums like these.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Before we go&lt;/h2&gt;
&lt;p&gt;Can you figure out the two proofs hidden in the logo of this post?&lt;/p&gt;
&lt;div class="center-aligner"&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2010/03/visual-math-friday.gif' alt='Visual Math Friday'&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Let me know in the comments if you can!&lt;/strong&gt;&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Get ahead of me&lt;/h2&gt;
&lt;p&gt;By the way, if you wish to get ahead of me in this series, you can get these three amazing books on visual proofs:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;&lt;a href="http://www.amazon.com/Proofs-without-Words-Exercises-Classroom/dp/0883857006?tag=catonmat-20"&gt;Proofs Without Words I: Exercises in Visual Thinking&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.amazon.com/Proofs-Without-Words-Exercises-Classroom/dp/0883857219?tag=catonmat-20"&gt;Proofs Without Words II: More Exercises in Visual Thinking&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.amazon.com/Math-Made-Visual-Understanding-Mathematics/dp/0883857464?tag=catonmat-20"&gt;Math Made Visual&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are these books on Amazon.com:&lt;/p&gt;
&lt;div class="center-aligner"&gt;&lt;table width="100%"&gt;&lt;tr align="center"&gt;&lt;td width="130"&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=freesciencand-20&amp;o=1&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;md=10FE9736YVPPT7A0FBG2&amp;asins=0883857006" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;
&lt;/td&gt;
&lt;td width="20"&gt;&lt;/td&gt;
&lt;td width="130"&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=freesciencand-20&amp;o=1&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;md=10FE9736YVPPT7A0FBG2&amp;asins=0883857219" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;
&lt;/td&gt;
&lt;td width="20"&gt;&lt;/td&gt;
&lt;td width="130"&gt;&lt;iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=freesciencand-20&amp;o=1&amp;p=8&amp;l=as1&amp;m=amazon&amp;f=ifr&amp;md=10FE9736YVPPT7A0FBG2&amp;asins=0883857464" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"&gt;&lt;/iframe&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=UKtOfIravfs:iks3zxNRKnw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=UKtOfIravfs:iks3zxNRKnw:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=UKtOfIravfs:iks3zxNRKnw:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=UKtOfIravfs:iks3zxNRKnw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=UKtOfIravfs:iks3zxNRKnw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=UKtOfIravfs:iks3zxNRKnw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=UKtOfIravfs:iks3zxNRKnw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/UKtOfIravfs" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/visual-math-friday</feedburner:origLink></entry>
  <entry xml:base="http://www.catonmat.net/feed">
    <title type="text">Vim Plugins You Should Know About, Part VII: ragtag.vim (formerly allml.vim)</title>
    <id>205</id>
    <updated>2010-03-08T17:19:49Z</updated>
    <published>2010-03-03T06:20:13Z</published>
    <link href="http://feedproxy.google.com/~r/catonmat/~3/TnmGzTWQbyc/vim-plugins-ragtag-allml-vim" />
    <author>
      <name>Peteris Krumins</name>
      <uri>http://www.catonmat.net/about</uri>
      <email>peter@catonmat.net</email>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Nxy0i2T6CrYvDVpP_lkK_cu3Kmc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Nxy0i2T6CrYvDVpP_lkK_cu3Kmc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Nxy0i2T6CrYvDVpP_lkK_cu3Kmc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Nxy0i2T6CrYvDVpP_lkK_cu3Kmc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;img src='http://www.catonmat.net/blog/wp-content/uploads/2008/12/vim-plugins-surround-vim.gif' alt='Vim Plugins, surround.vim' class="post-icon" align="left" /&gt;This is the seventh post in the article series "&lt;strong&gt;Vim Plugins You Should Know About&lt;/strong&gt;". This time I am going to introduce you to a plugin called "&lt;strong&gt;ragtag.vim&lt;/strong&gt;". A month ago it was still known as "&lt;strong&gt;allml.vim&lt;/strong&gt;" but now it has been renamed to &lt;strong&gt;ragtag.vim&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The best parts of RagTag are mappings for editing HTML tags. It has a mapping for quickly closing open HTML tags, a mapping for quickly turning the typed word into a pair of open/close HTML tags, several mappings for inserting HTML doctype, linking to CSS stylesheets, loading JavaScript &lt;code&gt;&amp;lt;script src="..."&gt;...&amp;lt;/script&gt;&lt;/code&gt; and it includes mappings for wrapping the typed text in a pair of &lt;code&gt;&amp;lt;?php ... ?&gt;&lt;/code&gt; tags for PHP, or &lt;code&gt;&amp;lt;% ... %&gt;&lt;/code&gt; for ASP or eRuby, and &lt;code&gt;{% .. %}&lt;/code&gt; for Django.&lt;/p&gt;
&lt;p&gt;RagTag is written by &lt;strong&gt;Tim Pope&lt;/strong&gt;. He's the master of Vim plugin programming. I have already written about two of his plugins - &lt;a href="http://www.catonmat.net/blog/vim-plugins-surround-vim/"&gt;surround.vim&lt;/a&gt; and &lt;a href="http://www.catonmat.net/blog/vim-plugins-repeat-vim/"&gt;repeat.vim&lt;/a&gt; and more articles about his plugins are coming!&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Previous articles in the series.&lt;/h2&gt;
&lt;ul&gt;	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-surround-vim/"&gt;Part I: surround.vim&lt;/a&gt; - find and edit surrounding parens, quotes, html tags, etc.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-repeat-vim/"&gt;Part II: repeat.vim&lt;/a&gt; - repeat the previous surrounding command.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-matchit-vim/"&gt;Part III: matchit.vim&lt;/a&gt; - extends the functionality of % key.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-snipmate-vim/"&gt;Part IV: snipmate.vim&lt;/a&gt; - the best snippet plugin for vim&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-a-vim/"&gt;Part V: a.vim&lt;/a&gt; - quickly change between source and header files (.c/.h).&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.catonmat.net/blog/vim-plugins-nerdtree-vim/"&gt;Part VI: nerd_tree.vim&lt;/a&gt; - awesome filesystem exploration plugin.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are examples of using the RagTag plugin.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Quickly closing an open HTML tag.&lt;/h2&gt;
&lt;p&gt;Suppose you have typed &lt;code&gt;&amp;lt;div&gt;&lt;/code&gt; and you want to close it without typing the whole closing tag &lt;code&gt;&amp;lt;/div&gt;&lt;/code&gt; yourself.&lt;/p&gt;
&lt;p&gt;The quick way to do it with RagTag is to press &lt;code&gt;&lt;strong&gt;CTRL+X /&lt;/strong&gt;&lt;/code&gt;. This mapping automatically closes the last open HTML tag.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Extra tip&lt;/strong&gt;: If you didn't have this plugin you could quickly close the tag by typing &lt;code&gt;&amp;lt;/&lt;/code&gt; and pressing &lt;code&gt;&lt;strong&gt;CTRL+X CTRL+O&lt;/strong&gt;&lt;/code&gt;. The default Vim mapping &lt;code&gt;&lt;strong&gt;CTRL+X CTRL+O&lt;/strong&gt;&lt;/code&gt; guesses the item that may come after the cursor. In case of an open HTML tag it's the close tag.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Creating a pair of open/close HTML tags from a word.&lt;/h2&gt;
&lt;p&gt;Suppose you want to quickly create a pair of &lt;code&gt;&amp;lt;div&gt;&amp;lt;/div&gt;&lt;/code&gt; and place the cursor between the two tags.&lt;/p&gt;
&lt;p&gt;The quick way to do it with RagTag is to type &lt;code&gt;div&lt;/code&gt; and press &lt;code&gt;&lt;strong&gt;CTRL+X SPACE&lt;/strong&gt;&lt;/code&gt;. This mapping takes the typed word and creates a pair of HTML tags, one closing tag and one open tag on the same line.&lt;/p&gt;
&lt;p&gt;However, if you wish to create open/close tag pair separated by a newline, type &lt;code&gt;&lt;strong&gt;CTRL+X ENTER&lt;/strong&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is an example, if you just typed &lt;code&gt;div&lt;/code&gt; and then press &lt;code&gt;CTRL+X ENTER&lt;/code&gt; it will produce the following output:&lt;/p&gt;
&lt;pre &gt;
&amp;lt;div&gt;
&lt;strong&gt;|&lt;/strong&gt;
&amp;lt;/div&gt;
&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;strong&gt;|&lt;/strong&gt;&lt;/code&gt; indicates the position of cursor.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Insert HTML doctype.&lt;/h2&gt;
&lt;p&gt;If you type &lt;code&gt;&lt;strong&gt;CTRL+X !&lt;/strong&gt;&lt;/code&gt; RagTag will display a list of HTML doctypes to choose from. Defaults to HTML 4.01 Strict.&lt;/p&gt;
&lt;p&gt;This mapping is not that useful, given that I already introduced &lt;a href="http://www.catonmat.net/blog/vim-plugins-snipmate-vim/"&gt;snipmate.vim plugin&lt;/a&gt; for creating snippets. Using snipmate.vim you can create a snippet "h" that would insert the whole HTML structure, including doctype, html, body, title, meta tags, etc.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Link to a CSS stylesheet.&lt;/h2&gt;
&lt;p&gt;Typing &lt;code&gt;&lt;strong&gt;CTRL+X @&lt;/strong&gt;&lt;/code&gt; inserts the snippet for linking to a CSS stylesheet.&lt;/p&gt;
&lt;pre &gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;/stylesheets/&lt;strong&gt;|&lt;/strong&gt;.css&amp;quot;&gt;
&lt;/pre&gt;
&lt;p&gt;This is again not that useful, given that we have &lt;a href="http://www.catonmat.net/blog/vim-plugins-snipmate-vim/"&gt;snipmate.vim&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The mapping is easy to remember because &lt;code&gt;@&lt;/code&gt; is used for importing in CSS.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Insert meta content-type tag.&lt;/h2&gt;
&lt;p&gt;Typing &lt;code&gt;&lt;strong&gt;CTRL+X #&lt;/strong&gt;&lt;/code&gt; inserts the HTML meta tag for document's content type and encoding.&lt;/p&gt;
&lt;pre &gt;
&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=ISO-8859-1&amp;quot;&gt;
&lt;/pre&gt;
&lt;p&gt;The charset depends on document's charset. If it's utf-8, the mapping will set the charset to utf-8 in the meta tag.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Load JavaScript document.&lt;/h2&gt;
&lt;p&gt;Typing &lt;code&gt;&lt;strong&gt;CTRL+X $&lt;/strong&gt;&lt;/code&gt; links to a JavaScript file.&lt;/p&gt;
&lt;pre &gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;/javascripts/&lt;strong&gt;|&lt;/strong&gt;.js&amp;quot;&gt;&lt;/script&gt;
&lt;/pre&gt;
&lt;p&gt;The mapping is easy to remember because &lt;code&gt;$&lt;/code&gt; is a valid char in identifiers in many languages.&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Wrap the typed text in PHP, Django, eRuby template tags.&lt;/h2&gt;
&lt;p&gt;There are several different mappings for wrapping text in template tags. It's best to summarize them in the following table. The table assumes you had just typed "foo" and you are editing an eRuby document:&lt;/p&gt;
&lt;pre &gt;
Mapping    Result
---------  -----------
CTRL+X =   foo&amp;lt;%= &lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X +   &amp;lt;%= foo&lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X -   foo&amp;lt;% &lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X _   &amp;lt;% foo&lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X '   foo&amp;lt;%# &lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X &amp;quot;   &amp;lt;%# foo&lt;strong&gt;|&lt;/strong&gt; %&gt;
&lt;/pre&gt;
&lt;p&gt;What this table shows us is, for example, that if you have typed "foo" and press &lt;code&gt;&lt;strong&gt;CTRL+X _&lt;/strong&gt;&lt;/code&gt;, the plugin will wrap "foo" in &lt;code&gt;&amp;lt;% %&gt;&lt;/code&gt; tags and place the cursor after "foo".&lt;/p&gt;
&lt;h2 style="margin-bottom:10px"&gt;Summary of all the RagTag mappings.&lt;/h2&gt;
&lt;pre &gt;
CTRL+X /       Close the last open HTML tag
CTRL+X SPACE   Create open/close HTML tags from the typed word
CTRL+X CR      The same as CTRL+X SPACE but puts a newspace in between
CTRL+X !       Insert HTML doctype
CTRL+X @       Insert CSS stylesheet
CTRL+X #       Insert meta content-type meta tag
CTRL+X $       Load JavaScript document

For the following mappings, suppose that
you have typed "foo".

Mapping        Result
---------      -----------
CTRL+X =       foo&amp;lt;%= &lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X +       &amp;lt;%= foo&lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X -       foo&amp;lt;% &lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X _       &amp;lt;% foo&lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X '       foo&amp;lt;%# &lt;strong&gt;|&lt;/strong&gt; %&gt;
CTRL+X &amp;quot;       &amp;lt;%# foo&lt;strong&gt;|&lt;/strong&gt; %&gt;
&lt;/pre&gt;
&lt;h2 style="margin-bottom:10px"&gt;How to install ragtag.vim?&lt;/h2&gt;
&lt;p&gt;To get the latest version:&lt;/p&gt;
&lt;ul&gt;	&lt;li&gt;1. Download &lt;a href="http://www.vim.org/scripts/script.php?script_id=1896"&gt;ragtag.zip&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;2. Extract ragtag.zip to &lt;code&gt;~/.vim&lt;/code&gt; (on Unix/Linux) or &lt;code&gt;~\vimfiles&lt;/code&gt; (on Windows).&lt;/li&gt;
	&lt;li&gt;3. Run &lt;code&gt;:helptags ~/.vim/doc&lt;/code&gt; (on Unix/Linux) or &lt;code&gt;:helptags ~\vimfiles\doc&lt;/code&gt; (on Windows) to rebuild the tags file (so that you can read help &lt;code&gt;:help ragtag&lt;/code&gt;.)&lt;/li&gt;
	&lt;li&gt;4. Restart Vim or source ragtag.vim by typing &lt;code&gt;:so ~/.vim/plugin/ragtag.vim&lt;/code&gt; (on Unix/Linux) or &lt;code&gt;:so ~\vimfiles\plugin\ragtag.vim&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style="margin-bottom:10px"&gt;Have Fun!&lt;/h2&gt;
&lt;p&gt;Have fun closing those HTML tags and until next time!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=TnmGzTWQbyc:oWE_sRIiN1I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=TnmGzTWQbyc:oWE_sRIiN1I:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=TnmGzTWQbyc:oWE_sRIiN1I:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=TnmGzTWQbyc:oWE_sRIiN1I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=TnmGzTWQbyc:oWE_sRIiN1I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/catonmat?a=TnmGzTWQbyc:oWE_sRIiN1I:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/catonmat?i=TnmGzTWQbyc:oWE_sRIiN1I:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/catonmat/~4/TnmGzTWQbyc" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://www.catonmat.net/blog/vim-plugins-ragtag-allml-vim</feedburner:origLink></entry>
</feed>
