website/build/blog/The Joy of One-Liners/index.html

264 lines
18 KiB
HTML

<!doctype html>
<html lang="en">
<center>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="/static/stylesheet.css">
<title>Stefan's Blog</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<div class="menu">
<a href="/" style="text-decoration:none">Stefan Friese's Website</a>
</div>
<style>
/* Stylesheet 1 */
body { background: #2f333d; color: #979fad; }
hr{ color: #979fad; border-color: #979fad; }
pre { background: #282c34; color: #979fad; border: 1px solid #282c34; }
code { background: #282c34; color: #979fad; }
a:hover { color: #be5046; }
details > summary { background: #282c34; }
details > summary:hover { background: #2f333d; color: #979fad; }
::selection { background: #668799; }
::-moz-selection { background: #668799; }
</style>
<hr style="width: 36ch;"/>
<div class="menu">
<a href="/about.html" style="text-decoration:none">about&emsp;</a>
<a href="/contact.html" style="text-decoration:none">contact&emsp;</a>
<a href="/rss.xml" style="text-decoration:none">rss&emsp;</a>
<a href="https://git.stefan.works" style="text-decoration:none">git</a>
</div>
<br><br>
<p></p>
<hr/>
</center>
<p></p>
</head>
<body>
<div lang="en" class="content">
<span class="body">
<!-- 2022-05-29 -->
<style>pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.codehilite .hll { background-color: #ffffcc }
.codehilite .c { color: #7F848E } /* Comment */
.codehilite .err { color: #ABB2BF } /* Error */
.codehilite .esc { color: #ABB2BF } /* Escape */
.codehilite .g { color: #ABB2BF } /* Generic */
.codehilite .k { color: #C678DD } /* Keyword */
.codehilite .l { color: #ABB2BF } /* Literal */
.codehilite .n { color: #E06C75 } /* Name */
.codehilite .o { color: #56B6C2 } /* Operator */
.codehilite .x { color: #ABB2BF } /* Other */
.codehilite .p { color: #ABB2BF } /* Punctuation */
.codehilite .ch { color: #7F848E } /* Comment.Hashbang */
.codehilite .cm { color: #7F848E } /* Comment.Multiline */
.codehilite .cp { color: #7F848E } /* Comment.Preproc */
.codehilite .cpf { color: #7F848E } /* Comment.PreprocFile */
.codehilite .c1 { color: #7F848E } /* Comment.Single */
.codehilite .cs { color: #7F848E } /* Comment.Special */
.codehilite .gd { color: #ABB2BF } /* Generic.Deleted */
.codehilite .ge { color: #ABB2BF } /* Generic.Emph */
.codehilite .gr { color: #ABB2BF } /* Generic.Error */
.codehilite .gh { color: #ABB2BF } /* Generic.Heading */
.codehilite .gi { color: #ABB2BF } /* Generic.Inserted */
.codehilite .go { color: #ABB2BF } /* Generic.Output */
.codehilite .gp { color: #ABB2BF } /* Generic.Prompt */
.codehilite .gs { color: #ABB2BF } /* Generic.Strong */
.codehilite .gu { color: #ABB2BF } /* Generic.Subheading */
.codehilite .gt { color: #ABB2BF } /* Generic.Traceback */
.codehilite .kc { color: #E5C07B } /* Keyword.Constant */
.codehilite .kd { color: #C678DD } /* Keyword.Declaration */
.codehilite .kn { color: #C678DD } /* Keyword.Namespace */
.codehilite .kp { color: #C678DD } /* Keyword.Pseudo */
.codehilite .kr { color: #C678DD } /* Keyword.Reserved */
.codehilite .kt { color: #E5C07B } /* Keyword.Type */
.codehilite .ld { color: #ABB2BF } /* Literal.Date */
.codehilite .m { color: #D19A66 } /* Literal.Number */
.codehilite .s { color: #98C379 } /* Literal.String */
.codehilite .na { color: #E06C75 } /* Name.Attribute */
.codehilite .nb { color: #E5C07B } /* Name.Builtin */
.codehilite .nc { color: #E5C07B } /* Name.Class */
.codehilite .no { color: #E06C75 } /* Name.Constant */
.codehilite .nd { color: #61AFEF } /* Name.Decorator */
.codehilite .ni { color: #E06C75 } /* Name.Entity */
.codehilite .ne { color: #E06C75 } /* Name.Exception */
.codehilite .nf { color: #61AFEF; font-weight: bold } /* Name.Function */
.codehilite .nl { color: #E06C75 } /* Name.Label */
.codehilite .nn { color: #E06C75 } /* Name.Namespace */
.codehilite .nx { color: #E06C75 } /* Name.Other */
.codehilite .py { color: #E06C75 } /* Name.Property */
.codehilite .nt { color: #E06C75 } /* Name.Tag */
.codehilite .nv { color: #E06C75 } /* Name.Variable */
.codehilite .ow { color: #56B6C2 } /* Operator.Word */
.codehilite .pm { color: #ABB2BF } /* Punctuation.Marker */
.codehilite .w { color: #ABB2BF } /* Text.Whitespace */
.codehilite .mb { color: #D19A66 } /* Literal.Number.Bin */
.codehilite .mf { color: #D19A66 } /* Literal.Number.Float */
.codehilite .mh { color: #D19A66 } /* Literal.Number.Hex */
.codehilite .mi { color: #D19A66 } /* Literal.Number.Integer */
.codehilite .mo { color: #D19A66 } /* Literal.Number.Oct */
.codehilite .sa { color: #98C379 } /* Literal.String.Affix */
.codehilite .sb { color: #98C379 } /* Literal.String.Backtick */
.codehilite .sc { color: #98C379 } /* Literal.String.Char */
.codehilite .dl { color: #98C379 } /* Literal.String.Delimiter */
.codehilite .sd { color: #98C379 } /* Literal.String.Doc */
.codehilite .s2 { color: #98C379 } /* Literal.String.Double */
.codehilite .se { color: #98C379 } /* Literal.String.Escape */
.codehilite .sh { color: #98C379 } /* Literal.String.Heredoc */
.codehilite .si { color: #98C379 } /* Literal.String.Interpol */
.codehilite .sx { color: #98C379 } /* Literal.String.Other */
.codehilite .sr { color: #98C379 } /* Literal.String.Regex */
.codehilite .s1 { color: #98C379 } /* Literal.String.Single */
.codehilite .ss { color: #98C379 } /* Literal.String.Symbol */
.codehilite .bp { color: #E5C07B } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #56B6C2; font-weight: bold } /* Name.Function.Magic */
.codehilite .vc { color: #E06C75 } /* Name.Variable.Class */
.codehilite .vg { color: #E06C75 } /* Name.Variable.Global */
.codehilite .vi { color: #E06C75 } /* Name.Variable.Instance */
.codehilite .vm { color: #E06C75 } /* Name.Variable.Magic */
.codehilite .il { color: #D19A66 } /* Literal.Number.Integer.Long */</style>
<p>2022-05-29</p>
<h1 id="the-joy-of-one-liners">The Joy of One-Liners</h1>
<p>There is an engineering idiom which withstands time like no other. As
old as the hills but never forgotten. In informational technology
relations, one could say it is ancient. Its dawn proclaimed from the
shores of Seattle, defeated by an apocalyptic horseman with the
melodious name <em>NT</em>. Shot! Point blank into the chest. Buried under the
hills of an IT dark age which we call the nineties, dead. But is it?
Well, not exactly. There is still life in the old dog. Like Beatrix
Kiddo, it one-inch punches itself back to daylight. Coal black as a
miner. Topsoil sticks to its beige 1978's leather jacket, it trickles to
the ground with every step taken to the nearest diner. The door opens
again. "May I have a glass of water, please?"</p>
<p>An art passed down from the ancestors. Its most visible interface: <em>The
Shell</em>. Its name: <em>The Unix Philosophy</em>.</p>
<p>Coined by Doug McIlroy in the <a href="https://archive.org/details/bstj57-6-1899/mode/2up">Bell System Technical
Journal</a> as a
foreword to the UNIX Time-Sharing System. There is an even more concise
version<a href="#references">[1]</a> and
according to <a href="http://www.catb.org/~esr/writings/taoup/html/ch01s06.html">Eric Steven
Raymond</a> this
is <a href="#references">[2]</a>:</p>
<blockquote>
<p>"This is the Unix philosophy: Write programs that do one thing and do
it well. Write programs to work together. Write programs to handle
text streams, because that is a universal interface."<br />
--- Doug McIlroy ---</p>
</blockquote>
<p>In some way, this is similar to the concept of the on vogue philosophy
of microservices everywhere. Services are written to do one thing and do
it well. They work together. Also, text is the connecting link between
programs, services, and humans. The possibility to read a program's
output as text seems benign, as long as everything is working well. The
advantage is interactivity at any time, testability of every component,
and debuggability at every step of the process in an on the fly manner.
Impromptu, out of reflex like a punch.</p>
<h2 id="pipe-dreams"><a href="#pipe-dreams">Pipe Dreams</a></h2>
<hr />
<p>Mc Ilroy made another very important contribution, which is the Unix
pipe. It is the practical implementation of connecting the programs
inside the shell. He saw the programs as tools, plugged together via
pipes building a
<a href="http://www.princeton.edu/~hos/Mahoney/expotape.htm">toolbox</a>. Program
A's <code>stdout</code> is put into the <code>stdin</code> of program B. This leaves us with a
single line of chained, well-defined programs to solve a problem that
would otherwise be an extensive, multi-line program in any programming
language of your choice.</p>
<p>Let's say we've got two programs. The first is one is <em>fortune</em>, the
fortune cookie program from BSD games, which outputs random quotes as
text. The second one is <em>cowsay</em>, which displays various kinds of
animals as ASCII art. In order to work in a coherent manner a <code>|</code> is
used. The pipe connects the first one to the second one.</p>
<div class="codehilite"><pre><span></span><code>fortune<span class="w"> </span><span class="p">|</span><span class="w"> </span>cowsay
<span class="w"> </span>_________________________________________
<span class="w"> </span>/<span class="w"> </span>Gil-galad<span class="w"> </span>was<span class="w"> </span>an<span class="w"> </span>Elven-king.<span class="w"> </span>Of<span class="w"> </span>him<span class="w"> </span>the<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>harpers<span class="w"> </span>sadly<span class="w"> </span>sing:<span class="w"> </span>the<span class="w"> </span>last<span class="w"> </span>whose<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>realm<span class="w"> </span>was<span class="w"> </span>fair<span class="w"> </span>and<span class="w"> </span>free<span class="w"> </span>between<span class="w"> </span>the<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>Mountains<span class="w"> </span>and<span class="w"> </span>the<span class="w"> </span>Sea.<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>His<span class="w"> </span>sword<span class="w"> </span>was<span class="w"> </span>long,<span class="w"> </span>his<span class="w"> </span>lance<span class="w"> </span>was<span class="w"> </span>keen,<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>his<span class="w"> </span>shining<span class="w"> </span>helm<span class="w"> </span>afar<span class="w"> </span>was<span class="w"> </span>seen<span class="p">;</span><span class="w"> </span>the<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>countless<span class="w"> </span>stars<span class="w"> </span>of<span class="w"> </span>heaven<span class="err">&#39;</span>s<span class="w"> </span>field<span class="w"> </span>were<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>mirrored<span class="w"> </span><span class="k">in</span><span class="w"> </span>his<span class="w"> </span>silver<span class="w"> </span>shield.<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>But<span class="w"> </span>long<span class="w"> </span>ago<span class="w"> </span>he<span class="w"> </span>rode<span class="w"> </span>away,<span class="w"> </span>and<span class="w"> </span>where<span class="w"> </span>he<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>dwelleth<span class="w"> </span>none<span class="w"> </span>can<span class="w"> </span>say<span class="p">;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span>into<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>darkness<span class="w"> </span>fell<span class="w"> </span>his<span class="w"> </span>star<span class="w"> </span><span class="k">in</span><span class="w"> </span>Mordor<span class="w"> </span>where<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span>the<span class="w"> </span>shadows<span class="w"> </span>are.<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="se">\ </span>--<span class="w"> </span>J.<span class="w"> </span>R.<span class="w"> </span>R.<span class="w"> </span>Tolkien<span class="w"> </span>/
<span class="w"> </span>-----------------------------------------
<span class="w"> </span><span class="se">\ </span><span class="w"> </span>^__^
<span class="w"> </span><span class="se">\ </span><span class="w"> </span><span class="o">(</span>oo<span class="o">)</span><span class="se">\_</span>______
<span class="w"> </span><span class="o">(</span>__<span class="o">)</span><span class="se">\ </span><span class="w"> </span><span class="o">)</span><span class="se">\/\</span>
<span class="w"> </span><span class="o">||</span>----w<span class="w"> </span><span class="p">|</span>
<span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">||</span>
</code></pre></div>
<p>To mix in some colors pipe everything through lolcat. Try it out!</p>
<div class="codehilite"><pre><span></span><code>fortune<span class="w"> </span><span class="p">|</span><span class="w"> </span>cowsay<span class="w"> </span><span class="p">|</span><span class="w"> </span>lolcat
</code></pre></div>
<p>So far so good, let us gain some real-world practice.</p>
<h2 id="punching-lines-and-retire-your-password-generator"><a href="#punching-lines-and-retire-your-password-generator">Punching Lines and Retire Your Password Generator</a></h2>
<hr />
<p>Have you ever questioned the integrity of your one-click, GUI,
proprietary password generator? Is its randomness really as
unpredictable as it proclaims? Are you the only one which ends up
knowing your generated password? There is a one-liner that ups your
opsec instantly. Right from the source of randomness:</p>
<div class="codehilite"><pre><span></span><code>head<span class="w"> </span>-n<span class="w"> </span><span class="m">42</span><span class="w"> </span>/dev/urandom<span class="w"> </span><span class="p">|</span><span class="w"> </span>tr<span class="w"> </span>-cd<span class="w"> </span><span class="s1">&#39;[:alnum:]&#39;</span><span class="w"> </span><span class="p">|</span><span class="w"> </span>cut<span class="w"> </span>-c-12
</code></pre></div>
<p>So, what is going on here? Everything is a file, that is the way *nix
systems see it, even the device which puts out random data. To read the
upper part of a file we use <code>head</code>. It will be sent to <code>stdout</code> and
displayed via the shell. Parameter <code>-n</code> reads exactly 42 lines of the
file given to gather enough randomness. The output of <code>head</code> will be
sent to <code>tr</code>. In order to select only alphanumeric characters for our
password, we use <code>'[:alnum:]'</code>. Parameters <code>-c</code> selects the complement
of alphanumeric characters and <code>-d</code> deletes them. <code>cut</code> does exactly
what it says, <code>-c-12</code> cuts after 12 characters with leaves us with a
random password of length 12. Every time you execute this one-liner a
freshly made random password is returned.</p>
<p>To extend the pool of possible symbols the manual of <code>tr</code> lists various
sets of filtered symbols. In the case of a password generator, further
sensible filters are <code>'[:alpha:]'</code> or <code>'[:digit:]'</code>. While <code>'[:graph:]'</code>
is also viable in this case it returns one of the greater sets of
symbols. Use it with caution, especially if you create passwords for
database users. These might be terminated prematurely through <code>`</code> or
<code>'</code> inside the returned string.</p>
<h2 id="sunday-punch"><a href="#sunday-punch">Sunday Punch</a></h2>
<hr />
<p>This blog entrance can be seen as a prelude to a series of one-liners I
use time and time again. The are multiple in the pipeline. One-liners
should save you the time you otherwise would spend coding a complex
solution. There is little better than solving a challenging problem in a
single line.</p>
<h2 id="references"><a href="#references">References</a></h2>
<p><a href="https://www.bookfinder.com/?isbn=9780201547771">[1] A Quarter Century of Unix, 1994, Peter Salus,
ISBN:9780201547771</a><br />
<a href="https://www.bookfinder.com/?isbn=9780131429017">[2] The Art of UNIX Programming, 2003, Eric Raymond,
ISBN:9780131429017</a></p>
</span>
</div>
<div id="footer">
<hr/>
<p></p>
<center>
&copy; Stefan Friese
</center>
</div>
</body>
</html>