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

<channel>
	<title>TechKnack &#187; linux</title>
	<atom:link href="http://techknack.net/category/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://techknack.net</link>
	<description>The rantings of a techie</description>
	<lastBuildDate>Thu, 24 Dec 2009 19:53:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SVN setup</title>
		<link>http://techknack.net/svn-setup/</link>
		<comments>http://techknack.net/svn-setup/#comments</comments>
		<pubDate>Sun, 30 Aug 2009 01:32:24 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=376</guid>
		<description><![CDATA[Recently I set up an SVN repository in the hopes that maybe I can show off some of my programming work to potential clients (or maybe just other people who are interested).  I ran into sufficient trouble during setup that I thought it would be a good idea to give a run-down of my [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I set up an SVN repository in the hopes that maybe I can show off some of my programming work to potential clients (or maybe just other people who are interested).  I ran into sufficient trouble during setup that I thought it would be a good idea to give a run-down of my setup for others.</p>
<p>My setup runs on Apache/Linux, on a subdomain of one of my sites.  I have a root SVN directory that can hold multiple repositories.  While the repos are accessible via SVN, you can also browse them through a web interface (though it&#8217;s fairly simple, basically just lists of &#8220;directory&#8221; contents).  The repos give anonymous access for checkouts and other &#8220;read&#8221; functions, but are login-protected for commits and other &#8220;write&#8221; functions.</p>
<p>The guides I came across for setting up SVN mostly want you to put your settings in the file /etc/apache2/mods-available/dav_svn.conf , but I found that it works just fine if you set it up like a regular site/subdomain.  That is, as a VirtualHost entry in a file in /etc/apache2/sites-available.  So here is my VHost entry for SVN:</p>
<pre class="brush: xml;">
&lt;VirtualHost *&gt;
        ServerName svn.eternicode.com
        &lt;Location /&gt;
                Order allow,deny
                Allow from all
                DAV svn
                SVNParentPath /var/www/svn
                SVNListParentPath on
                AuthType Basic
                AuthName &quot;Eternicode SVN Repo&quot;
                AuthUserFile /etc/apache2/mods-available/dav_svn.passwd
                &lt;LimitExcept GET PROPFIND OPTIONS REPORT&gt;
                        Require valid-user
                &lt;/LimitExcept&gt;
        &lt;/Location&gt;
        ErrorLog /var/log/apache2/error_svn.log
        CustomLog /var/log/apache2/access_svn.log combined
&lt;/VirtualHost&gt;
</pre>
<p>Most of the special, SVN-specific stuff comes inside the &lt;Location&gt; tags; the ServerName, ErrorLog, and CustomLog are standard Apache directives.</p>
<p>SVNParentPath is the &#8220;root&#8221; repo directory; your various repos will be below this directory.  If you only want to host a single repo here, change the directive to just &#8220;SVNPath&#8221;.  The SVNListParentPath allows web access to a listing of all available repos; if you use SVNPath, remove SVNListParentPath.  If SVNListParentPath is off or omitted, users will get a 403 Forbidden error when browsing the parent directory.</p>
<p>AuthType, AuthName, and AuthUserFile define the login settings; the AuthUserFile is created with the htpasswd command.</p>
<p>The LimitExcept section is where we differentiate between anonymous reads and protected writes.  For everything other than GET, PROPFIND, OPTIONS, and REPORT methods, we want to Require a valid-user; if someone wants to commit, they have to authenticate according to the AuthUserFile defined above.</p>
<p>One issue I ran into was that, after everything was seemingly set up properly, any svn commands would result in a &#8220;Moved Permanently&#8221; error.  It turned out that I had defined the DocumentRoot to also be /var/www/svn; this would conflict with the svn settings, confuse apache, and result in the Moved error.  Don&#8217;t include a DocumentRoot; the svn setup will take care of everything once you give it an SVNParentPath.</p>
<p>Credits: Sematopia.com has a <a href="http://www.sematopia.com/?p=66">nice little guide</a> that takes you through steps outside of the apache configuration (though their 4-line apache config is scarily sparse).  Sellersrank.com has a guide for <a href="http://www.sellersrank.com/ubuntu/setup-apache-subversion-ssl-https-with-virtual-hosts-on-ubuntu/">setting up Apache-run SVN over https</a>; though I&#8217;m not using https, this guide helped me get my settings right.  </p>
<p>A few notes: Don&#8217;t use a DocumentRoot, only use the SVNParentPath.  Make sure the parent path is owned by user and group www-data (or whatever user your apache instance uses).  You can ensure this by:</p>
<pre class="brush: bash;">
$ sudo chown -R www-data.www-data /var/www/svn
</pre>
<p>While it would be extremely nice to be able to create new repositories with a simple &#8220;svn import&#8221;, it seems svn&#8217;s capabilities are restricted in that area.  It wouldn&#8217;t be too difficult to set up a cron job to monitor the SVN logs and create new repos as required, but that&#8217;d be hacky and inadequate. To create a new repository, you first have to run</p>
<pre class="brush: bash;">
$ sudo svnadmin create /var/www/svn/new_repo
</pre>
<p>on the server.  However, in order to not have issues with the fact that the web server owns all the svn files, I&#8217;d recommend creating new repos as the www-data user:</p>
<pre class="brush: bash;">
$ sudo su www-data -c &quot;svnadmin create /var/ww/svn/new_repo&quot;
</pre>
<p>Once the initial repo structure is created, you can then use &#8220;svn import&#8221; on a remote machine to import the first revision.</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=376&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/svn-setup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash rpad, lpad, and &#8220;center-pad&#8221;</title>
		<link>http://techknack.net/bash-rpad-lpad-and-center-pad/</link>
		<comments>http://techknack.net/bash-rpad-lpad-and-center-pad/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 21:09:57 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=297</guid>
		<description><![CDATA[One thing it seems bash has no tool for is padding strings.  If you want to left-pad a number (say, 3) with zeros to a certain &#8220;string width&#8221; (say, 5 characters wide), you could do:

$ echo `printf &#34;%05d&#34; 3`
00003

However, this only works with numbers.  Actually, it only works with integers (bash can&#8217;t handle [...]]]></description>
			<content:encoded><![CDATA[<p>One thing it seems bash has no tool for is padding strings.  If you want to left-pad a number (say, 3) with zeros to a certain &#8220;string width&#8221; (say, 5 characters wide), you could do:</p>
<pre class="brush: bash;">
$ echo `printf &quot;%05d&quot; 3`
00003
</pre>
<p>However, this only works with numbers.  Actually, it only works with integers (bash can&#8217;t handle floats, apparently).  Worse, it only pads on the left with zeros.  No right-padding, no &#8220;other character&#8221; padding.</p>
<pre class="brush: bash;">
$ echo `printf &quot;%05d&quot; -`
bash: printf: -: invalid number
00000
$ echo `printf &quot;%05s&quot; -`
-
</pre>
<p>Breaking out of numbers and into string concatenation, however, makes it a bit easier:</p>
<pre class="brush: bash;">
function lpad {
    word=&quot;$1&quot;
    while [ ${#word} -lt $2 ]; do
        word=&quot;$3$word&quot;;
    done;
    echo &quot;$word&quot;;
}
$ lpad 3 5 0
00003
</pre>
<p>&#8220;But it&#8217;s the same output!&#8221; you say?  Well, for this input it happens to be, yes.</p>
<pre class="brush: bash;">
$ lpad 4 5 -
----4
$ lpad hello 11 -
------hello
$ lpad hello 11 !
!!!!!!hello
</pre>
<p>We can even pad with whitespace:</p>
<pre class="brush: bash;">
$ echo &quot;'`lpad hello 11 \ `'&quot;
'      hello'
</pre>
<p>Here I&#8217;ve printed single quotes around the results to show the space padding, and used the backslash to escape the space in the command, so it would be used as $3 rather than be seen as CLI whitespace (and ignored).</p>
<p>Of course, this function can be switched around to make an rpad function, and extended to make a cpad function:</p>
<pre class="brush: bash;">
function rpad {
    word=&quot;$1&quot;
    while [ ${#word} -lt $2 ]; do
        word=&quot;$word$3&quot;;
    done;
    echo &quot;$word&quot;;
}
function cpad {
    word=&quot;$1&quot;
    while [ ${#word} -lt $2 ]; do
        word=&quot;$word$3&quot;;
        if [ ${#word} -lt $2 ]; then
            word=&quot;$3$word&quot;
        fi;
    done;
    echo &quot;$word&quot;;
}
$ rpad &quot;w00t&quot; 15 ^
w00t^^^^^^^^^^^
$ cpad &quot;hello, world&quot; 50 -
-------------------hello, world-------------------
</pre>
<p>Of course, these functions aren&#8217;t perfect, as they make (at least) the following assumptions:</p>
<ol>
<li>Inputs $1 (word to pad), $2 (length to pad to), and $3 (padding characters) are given.</li>
<li>Input $2 is a number.</li>
<li>Input $3 is one character, and no more.</li>
</ol>
<p>Assumption #1 means that if, for example, only $1 and $2 are given, the function will go into an infinite loop (or actually exit with an error, &#8220;bash: [: 8: unary operator expected").  This can be fixed by checking for those variables' existence, and initializing some internal variables to default values if they are not:</p>
<pre class="brush: bash;">
function lpad {
    if [ &quot;$1&quot; ]; then
        word=&quot;$1&quot;;
    else
        word=&quot;&quot;;
    fi;

    if [ &quot;$2&quot; ]; then
        len=$2;
    else
        len=${#word};
    fi;

    if [ &quot;$3&quot; ]; then
        padding=&quot;$3&quot;;
    else
        padding=&quot; &quot;;
    fi;

    while [ ${#word} -lt $len ]; do
        word=&quot;$padding$word&quot;;
    done;
    echo &quot;$word&quot;;
}
</pre>
<p>Here, the "word" defaults to a blank string, the "length" defaults to the length of the word, and the "padding" defaults to a space.  If only the word is given, the word will be returned.  If word and length are given, word will be padded with spaces.  If all three are given, it works fine.</p>
<p>Assumption #2 means that if $2 is a string containing anything other than digits 0-9, the function will exit with an error ("bash: [: &lt;length&gt;: integer expression expected").  This can be fixed by "filtering" any non-digit characters out of the length string:</p>
<pre class="brush: bash;">
    if [ &quot;$2&quot; ]; then
        len=$((`echo $2 | sed 's/[^0-9]//g'`));
    else
        len=${#word};
    fi;
</pre>
<p>This uses the sed tool, which should be available on most if not all *nix systems, to replace all non-digits ([^0-9], in regex notation) with nothing, then converts the result from a string of numbers to an actual number with $(()).  This means that "5uh0oh0" will be turned into 500.  We'll get a scary big string in that case, but at least we won't get errors!</p>
<p>Assumption #3 means that if the pad string is more than one character, the result *could* be longer than the length we wanted.  For example:</p>
<pre class="brush: bash;">
$ string=`cpad hey 50 -`
$ echo ${#string}
50
$ string=`cpad hey 50 -=`
$ echo ${#string}
51
</pre>
<p>In the second example there, the length of the output string actually has one extra character.  This is because the function only adds the padding while the length of the string is less than our specified length; it doesn't actually do any length-checking once we've gone beyond the "length less than" test.  This is fixed slightly less simply, and requires different logic for each function:</p>
<pre class="brush: bash;">
function rpad {
    ...
    while [ ${#word} -lt $len ]; do
        word=&quot;$word$padding&quot;;
    done;
    while [ ${#word} -gt $len ]; do
        word=${word:0:$((${#word}-1))}
    done;
    echo &quot;$word&quot;;
}
function lpad {
    ...
    while [ ${#word} -lt $len ]; do
        word=&quot;$padding$word&quot;;
    done;
    while [ ${#word} -gt $len ]; do
        word=${word:1:$((${#word}-1))}
    done;
    echo &quot;$word&quot;;
}
function cpad {
    ...
    while [ ${#word} -lt $len ]; do
        word=&quot;$word$padding&quot;;
        if [ ${#word} -lt $len ]; then
            word=&quot;$padding$word&quot;
        fi;
    done;
    while [ ${#word} -gt $len ]; do
        word=${word:0:$((${#word}-1))}
        if [ ${#word} -gt $len ]; then
            word=${word:1:$((${#word}-1))}
        fi;
    done;
    echo &quot;$word&quot;;
}
</pre>
<p>The solution uses the bash substring notation, ${variable:start:length}, to strip off extra characters at the end/beginning when the resulting string is too long.  Of course, this isn't a perfect fix; if you specify a shorter length than your input string, the string will simply be truncated to that length.  Also, if you use a long string for padding with cpad, you'll get unbalanced output.</p>
<pre class="brush: bash;">
$ lpad &quot;hello, world&quot; 5
world
$ rpad &quot;hello, world&quot; 5
hello
$ cpad &quot;hello, world&quot; 5
lo, w
$ cpad hello 50 ---=--=---
-=--=------=--=---hello---=--=------=--=------=--=
</pre>
<p>You could easily continue to refine this function to make it obey all sorts of preconceptions, but I'm going to stop here.  If you use the functions as they're meant to be used -- numerical lengths and single-character paddings, etc -- it'll all be fine.</p>
<p>Though if you do find a nice, concise way to make these behave "properly", feel free to share in the comments!</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=297&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/bash-rpad-lpad-and-center-pad/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8220;Selective Top&#8221; Bash Script</title>
		<link>http://techknack.net/selective-top-bash-script/</link>
		<comments>http://techknack.net/selective-top-bash-script/#comments</comments>
		<pubDate>Fri, 29 May 2009 22:05:18 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=292</guid>
		<description><![CDATA[In my daily work on linux, I constantly have several tabs open in my console app for various CLI activites.  Normally, when I log in to a session, Yakuake auto-starts and I immediately open four tabs in it.  Tab four becomes a system monitor through the use of the &#8220;top&#8221; command, tab one [...]]]></description>
			<content:encoded><![CDATA[<p>In my daily work on linux, I constantly have several tabs open in my console app for various CLI activites.  Normally, when I log in to a session, Yakuake auto-starts and I immediately open four tabs in it.  Tab four becomes a system monitor through the use of the &#8220;top&#8221; command, tab one becomes an SSH window to my home server, and the other two are open for whatever.</p>
<p>Occasionally, I&#8217;ll want to keep an eye on specific processes and their resource usage, but they won&#8217;t show up in my &#8220;top&#8221; screen, no matter how I sort the fields.  At this point, I have to use &#8220;ps&#8221; to find the PID (process ID) of each process I want to watch and add each PID to the end of the &#8220;top&#8221; command (using the -p switch for each PID), just to watch a few specific processes.</p>
<p>This little process is well-defined and repeating.  Just the kind of task computers were designed to handle.  I wrote a bash script which takes any number of arguments &#8212; all of them names of processes you want to watch &#8212; finds all related PIDs, and tacks them on to a top command.</p>
<pre class="brush: bash;">
#!/bin/bash

ps=&quot;&quot;

for p in $*; do
    ps=&quot;$ps `ps -e | grep $p | awk '{print $1}' | sort -n | sed 's/^/-p /' | tr '\n' ' '`&quot;
done

while [ `echo &quot;$ps&quot; | grep -c &quot;  &quot;` -ne 0 ]; do
    ps=`echo &quot;$ps&quot; | sed 's/  / /'`
done
ps=`echo &quot;$ps&quot; | sed 's/\(^\s*\)\|\(\s*$\)//'`

if [ -z &quot;$ps&quot; ]; then
    echo &quot;No processes found.&quot;
else
    top $ps
fi
</pre>
<p><em>Please only use the above as a reference!</em>  The script uses a lot of single quotes, which WordPress likes to convert to &#8220;smart&#8221; quotes.  To see the script as it should be, you can <a href="/examples/bash/btm.txt">view the script as a text file</a>.</p>
<p>The first chunk (&#8221;for p in $*&#8230;&#8221;) iterates over all the arguments, pulling out all the associated PIDs.  The second block (&#8221;while&#8230;&#8221;) replaces multiple spaces with single spaces within the extracted process list, and trims any whitespace off of the beginning and end, to prepare the string for the test at the end.  The last part (&#8221;if [ -z&#8230;&#8221;) checks if the process list is empty or not (if it&#8217;s all spaces, it&#8217;s &#8220;not&#8221;).  If it is empty, the script alerts you and exits &#8212; you won&#8217;t get an empty top list (or full, since there are no arguments passed).  If it&#8217;s not empty, we can assume we found some PIDs, so we tack that on to the top command and take you straight there.</p>
<p>If you want to use this, just stick it in an executable file in your path (see &#8220;echo $PATH&#8221; at the command line); I simply named mine &#8220;btm&#8221;, but it doesn&#8217;t matter what you call it.  If you have any command line arguments you like to pass on to top, you can stick them between &#8220;top&#8221; and &#8220;$ps&#8221; in the &#8220;else&#8221; part of the script.  Once it&#8217;s all set up, just call the script with the process names you want to watch:</p>
<pre class="brush: bash;">$ btm rsync firefox thunderbird</pre>
<p>Keep in mind that this will only work with processes that are currently running &#8212; once that rsync job is done, it&#8217;ll disappear from the list, but no new rsync jobs will show up unless you re-run the script.</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=292&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/selective-top-bash-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Conky Transparency Fix for KDE4</title>
		<link>http://techknack.net/conky-transparency-fix-for-kde4/</link>
		<comments>http://techknack.net/conky-transparency-fix-for-kde4/#comments</comments>
		<pubDate>Fri, 08 May 2009 01:31:42 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=290</guid>
		<description><![CDATA[I love the feeling of power that comes from doing something that google couldn&#8217;t help with  
In this case, I&#8217;ve spent the past couple days messing with Conky (yes, it is as addicting as they say).  A google search will tell you what it is, and another will show you all the cool [...]]]></description>
			<content:encoded><![CDATA[<p>I love the feeling of power that comes from doing something that google couldn&#8217;t help with <img src='http://techknack.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>In this case, I&#8217;ve spent the past couple days messing with Conky (yes, it is as addicting as they say).  A google search will tell you what it is, and another will show you all the cool things it can do.  One thing that absolutely irked me, though, was the lack of transparency under KDE4.  Basically, my options were:</p>
<ol>
<li>Use &#8220;own_window_type override&#8221;, which seemed to allow transparency, but conky would crash unless I set use_xft to no.  So I got true transparency, but no sexy fonts.</li>
<li>Use &#8220;own_window_type normal&#8221;, and use sexy fonts with use_xft set to true, but using the &#8220;pseudo-transparency&#8221; that conky uses would use the wrong wallpaper.</li>
<li>Use #2 above, but set own_window_transparency to no, and use a solid color background.</li>
</ol>
<p>While I was tweaking conky, I was using #3.  Not the best I could hope for, but the best I could get without any help.  And good enough for development.</p>
<p>When I asked google for help, I found out several things:</p>
<ol>
<li>Conky uses the wallpaper set on the &#8220;root window&#8221; for its pseudo-transparency.</li>
<li>KDE4/Plasma uses its own desktop-drawing to draw the wallpaper.</li>
<li>KDE4/Plasma does not update the root window&#8217;s wallpaper when it updates the desktop&#8217;s wallpaper.</li>
<li>The latest and greatest KDE4 versions are phasing out DCOP support in favor of DBUS.  DCOP, coupled with a program called &#8220;feh&#8221;, is what many workarounds to this issue have used.</li>
<li>The DBUS interface to KDE4 is not yet fully developed, and, as such, has no way to get the current desktop wallpaper.</li>
<li>A method has been pieced together that <a href="http://bbs.archlinux.org/viewtopic.php?pid=549405">greps the user&#8217;s appletsrc file</a> to get the user-set wallpaper:
<pre class="brush: bash;">
feh --bg-scale &quot;`grep 'wallpaper=' ~/.kde4/share/config/plasma-appletsrc | tail --bytes=+11`&quot;
</pre>
</li>
<li>Nobody seems to have hacked together anything that works for those of us who use the slideshow feature of KDE4.</li>
</ol>
<p>Figures. Anyway, after some more digging around, I&#8217;ve created a script which fixes the problem for slideshow-users:</p>
<pre class="brush: bash;">
#!/bin/bash
# kde4bg - by Andrew Rowls &lt;andrew@techknack.net&gt;

SLIDEPATH=`grep slidepaths ~/.kde/share/config/plasma-appletsrc | tail --lines=1 | tail --bytes=+12`
WALL=`ls --sort=time --time=atime &quot;$SLIDEPATH&quot; | head --lines=1`
feh --bg-scale &quot;$SLIDEPATH/$WALL&quot;
</pre>
<p>Part one (SLIDEPATH) greps your appletsrc file for the directory(ies) set as your slidepath.  In the appletsrc file, this is probably a comma-separated list of directories, but I only wrote the script to handle one directory.  Also, you may have noticed that I used the directory ~/.kde rather than ~/.kde4.  I looked at the ctimes (modification times) of those files (basically, the times KDE4 last modified them).  The ctime for ~/.kde4/share/config/plasma-appletsrc was about 5 days earlier than ~/.kde/share/config/plasma-appletsrc .  A little further digging, and I found that the &#8220;kde4 version&#8221; had an old path to my slideshow directory, while the &#8220;kde version&#8221; had the current (ie, correct) path.  If your KDE4 installation still uses ~/.kde4, change the directory appropriately.</p>
<p>Part two (WALL) gets the last-accessed file in that slidepath.  Basically, every time Plasma changes the wallpaper, it has to *access* the image file, read it into memory, and display it.  As long as the access times (read: wallpaper switches) are at least a minute apart, the current wallpaper will bubble to the top so we can grab its name.  This, of course, assumes that 1) only your slideshow images are in your slidepath directory and 2) you don&#8217;t go messing with those image files very often.</p>
<p>Finally, part three uses feh to set the root window&#8217;s wallpaper, giving it the full path to the image file.</p>
<p>Now, every time you run this script, it will find the last-accessed (presumably by Plasma itself) file and set it as the background, at which point Conky can use that image for its pseudo-transparency.  Since the script has to be manually run, you could put it on cron or as a part of Conky&#8217;s updating, like this:</p>
<pre class="brush: bash;">
${texeci 3 /path/to/kde4bg}
</pre>
<p>That&#8217;ll execute the script every 3 seconds from conky.  You could put it as every 1 second, but I noticed that, when I tried it, the cpu usage would get a little carried away.  3 seconds is enough to keep cpu usage down while keeping the &#8220;transparency&#8221; sufficiently up-to-date.</p>
<p>Quick disclaimer: This was just a quick throw-together script, written based on my needs.  The main issue with it right now is it only supports one slide directory.  In KDE4, you can set multiple directories, but I really don&#8217;t know what that would do to the script.  Probably just confuse it, but then it wouldn&#8217;t work.</p>
<p>Enjoy.</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=290&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/conky-transparency-fix-for-kde4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make Windows Act Like Linux</title>
		<link>http://techknack.net/make-windows-act-like-linux/</link>
		<comments>http://techknack.net/make-windows-act-like-linux/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 20:23:11 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=262</guid>
		<description><![CDATA[As I use Win7 more and more, there are things that I notice it doesn&#8217;t do that linux did do.  Virtual desktops, certain programs minimizing to the systray, clipboard history.  Small things, things that you normally would take for granted if you had them, but things that become very noticeable when they&#8217;re suddenly [...]]]></description>
			<content:encoded><![CDATA[<p>As I use Win7 more and more, there are things that I notice it doesn&#8217;t do that linux did do.  Virtual desktops, certain programs minimizing to the systray, clipboard history.  Small things, things that you normally would take for granted if you had them, but things that become very noticeable when they&#8217;re suddenly missing.  Fortunately, there are lots of little, independently developed programs that provide some of the little pieces of functionality that linux enthusiasts grow used to.</p>
<p>Before I begin listing off links, I feel the need to put a disclaimer.  I realize that the title for this post will make many laugh.  It makes me laugh.  Why, after all, would you want to make Windows act like Linux when you can have the real deal for free?  The answer is just that: Linux is not free, not in the modern sense.  The switch from windows to linux is a shift in the way your world works.  It&#8217;s often a shift for the better, but the shift itself almost always takes time &#8212; time to get used to a new ideology, time to figure things out, time to make things work just the way you want them to.  Time that many people don&#8217;t have.</p>
<p>Truth is, there is simply no way to make Windows akin to Linux in any way, shape, or form.  They are two different environments, two different philosophies.  However, thanks to third-party developers and a fairly open distribution platform (I&#8217;m looking at you, Apple), it&#8217;s possible to bring some functionality to the Windows desktop.  You can&#8217;t change its personality, but you can change its behavior.  This list is meant to bring some linux-y goodness to those without the time to jump in head first.</p>
<p>Now, with that out of the way, the list:</p>
<ul>
<li><b>Clipboard history</b>: something so small, so unnoticeable until you need it, and so nice to have when you do need it.  <a href="http://clipx.org/">ClipX</a>; 131K download; 252K footprint (no plugins, 25 items, text only).</li>
<li><b>Virtual desktops</b>: Most linux distros come with virtual desktops or workspaces.  Once you learn to work with them, you can&#8217;t work without them.  <a href="http://virtuawin.sourceforge.net/">VirtuaWin</a>; 385K download; 1.3M footprint (four desktops).  Won&#8217;t give you the Compiz cube, but you shouldn&#8217;t be expecting that anyways <img src='http://techknack.net/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  .</li>
<li><b>Window snapping</b>: a nice feature for those who like to work with non-maximized windows in the corners of their desktops.  <a href="http://ivanheckman.com/allsnap/">AllSnap</a>; 69.4K download; just over 1M footprint (portable version via startup folder, desktop snapping only)</li>
<li><b>Systray minimization</b>: I got used to Amarok minimizing to the systray, and I wanted Windows Media Player to do the same.  <a href="http://www.teamcti.com/trayit/trayit.htm">TrayIt!</a>; 327K download; just over 1M footprint (one window rule for WMP).</li>
<li><b>Launchy/Gnome-Do/Program Launcher</b>: I never had much luck with launchy under linux, so I ended up using Gnome-Do for app launching.  Win7, however, seems to do fine with its Start Menu searchbar.  No download, native footprint.</li>
<li><b>Wallpaper rotater</b>: while not strictly functional, it is nice to be able to choose a number of images to auto-rotate through as a wallpaper.  Win7 has this built in.  No download, native footprint.</li>
</ul>
<img src="http://techknack.net/?ak_action=api_record_view&id=262&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/make-windows-act-like-linux/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Linux-to-Windows Program Replacements</title>
		<link>http://techknack.net/linux-to-windows-program-replacements/</link>
		<comments>http://techknack.net/linux-to-windows-program-replacements/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 20:21:57 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=226</guid>
		<description><![CDATA[For the past couple of weeks, I&#8217;ve been using the Windows 7 beta.  A shocker, I know, but I&#8217;ve been able to find replacements for most of the software I use everyday in Linux.  The biggest hangups I&#8217;ve found so far are 1) lack of package manager (PLEASE, Microsoft, implement something to this [...]]]></description>
			<content:encoded><![CDATA[<p>For the past couple of weeks, I&#8217;ve been using the Windows 7 beta.  A shocker, I know, but I&#8217;ve been able to find replacements for most of the software I use everyday in Linux.  The biggest hangups I&#8217;ve found so far are 1) lack of package manager (PLEASE, Microsoft, implement something to this effect!), and 2) lack of some SSHfs capabilities.  I used SSHfs extensively under linux, and WinSCP just doesn&#8217;t cut it.</p>
<p>Moving from a well-established Linux environment to a squeaky-clean Windows environment is bound to be a bumpy experience without first determining suitable replacements for all the programs that one uses on a daily basis.  After my initial move-in, I was rather ad-hoc in finding replacements.  Now that I&#8217;ve found suitable replacements for my most-used programs, perhaps this list can help those of you looking to make n experimental switch.</p>
<ul>
<li><b>BitTorrent</b>: I do a lot of torrenting, so a good replacement for KTorrent is necessary.  uTorrent has so far served my purposes for the odd torrent, while I continue to use my <a href="http://techknack.net/torrent-management-system-with-rtorrent-and-bash/">automated torrent system</a> on my home server for TV shows and such.</li>
<li><b>IM client with AIM and IRC</b>: I sit on IRC channels all day long these days, occasionally throwing in a word or two, but mainly gleaning whatever knowledge I can from the chatter.  Also, I have an AIM account that is my main real-time online point-of-access.  I&#8217;ve gotten used to Kopete, but it&#8217;s lacking in just the right areas so as to make me dissatisfied with it.  Recently I&#8217;ve installed Pidgin (under Kubuntu), and I&#8217;ve found that it has its own quirks that I&#8217;m dissatisfied with, perhaps more so than with Kopete.  The release of kDE4-only Kubuntu 8.10 has further disappointed me: Kopete lost its IRC capabilities, and I was forced to use Konversation for IRC, but it has been an exceptional IRC program.  Here on Windows, the options are rather scarce &#8212; Pidgin is available, but suffers from the aforementioned shortcomings.  I&#8217;ve heard great things about Digsby, but it doesn&#8217;t seem to support IRC at the moment.  However, as I was forced to split my chatting between two programs on linux, doing the same on windows isn&#8217;t too bad a compromise.  I use Digsby for AIM, and <a href="http://www.silverex.org/">YChat</a>, which seems to be a branch of XChat, for IRC.  I am not completely satisfied with YChat as a Konversation replacement, because it has no auto-login, auto-identification, or auto-join features that work on Win7 (seems to be a dll issue here), but it works well enough.</li>
<li><b>Desktop Feed Reader</b>: My primary feed reader for feeds of interest to me is Google Reader, and that isn&#8217;t going to change.  However, I also use a desktop feed reader to toss temporary feeds like ebay and craigslist search results into.  On linux I&#8217;ve grown accustomed to using Akregator, simply because it&#8217;s included with Kubuntu.  Here on Windows, however, FeedDemon has taken the role quite nicely.</li>
<li><b>Music/Video playback</b>, a la Amarok/Kaffeine: I love my music.  And I love my video, whether it be downloaded TV shows or a DVD.  And I have to have some way to play them.  Regarding music, my needs are not outrageous &#8212; I just need some way to organize my music, fetch album info from the net, and perhaps display album art for me.  I don&#8217;t care for song ratings or anything fancy like that.  Windows Media Player works well in regards to both audio and video, and even works with my Inspiron&#8217;s front-side music player controls.</li>
<li><b>Gimp or PhotoShop</b>: Being in web development, I do occasionally do graphics editing.  For this, I need Gimp at the least, though I would like to try PhotoShop.  I&#8217;m going to attempt to install PS CS4 at some point, but I&#8217;m afraid I won&#8217;t have the free disk space for it.  Bummer.</li>
<li><b>Advanced text editor</b>: On Kubuntu, I used Kate for text editing (HTML, CSS, PHP, etc files).  My requirements here are syntax highlighting, tabs, and sessions.  Code collapsing is a nice feature, but not required.  I will likely use Notepad++ on Windows, though I haven&#8217;t done much development lately to really test its workflow yet.</li>
<li><b>Firefox, Thunderbird, and Sunbird</b>: I&#8217;m sorry, there is no replacement for these three <img src='http://techknack.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .</li>
<li><b>Office software</b>: On Linux, I got by fine using OpenOffice.  However, since I have free access to Office 2007, I am using that.  Sorry, OSS radicals.</li>
<li><b>Filezilla</b>: Again, no replacement.</li>
<li><b>PDF Viewer/Printer</b>: Another thing that comes stock with Kubuntu.  Foxit is good for PDF viewing, and <a href="http://www.acrosoftware.com/Products/CutePDF/writer.asp">CutePDF</a> works for a printer.</li>
<li><b>File manager</b>: Requirements in this area include all the things I&#8217;ve come to expect from Konqueror: tabbed interface (with spring-loaded tabs, no less), session management, and easy switching amongst various folder views (icons, details, etc).  CubicExplorer fits the bill quite nicely, though I still find myself opening Windows Explorer for short filemanaging stints.</li>
<li><b>SSHfs</b>: This was rather high on my priority list, as I have my web development folders, which reside on my server, mounted locally as SSHfs shares.  This means that, whenever I have internet access, I can simply open, edit, and save the files at home as if they were on my local machine.  Unfortunately, no SSHfs for Windows seems to exist.  I had heard things about Novell&#8217;s netdrive.exe, but it doesn&#8217;t support sftp.  Dokan&#8217;s SSHfs looked promising, but, alas, would not install on a Windows 7 environment (even in Vista compatibility mode).  For now, I have to resort to WinSCP for SSH-based editing, but it doesn&#8217;t come near the convenience of SSHfs.</li>
</ul>
<img src="http://techknack.net/?ak_action=api_record_view&id=226&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/linux-to-windows-program-replacements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using a 1D array like a 2D (or 3D) array</title>
		<link>http://techknack.net/using-a-1d-array-like-a-2d-or-3d-array/</link>
		<comments>http://techknack.net/using-a-1d-array-like-a-2d-or-3d-array/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 19:44:50 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=191</guid>
		<description><![CDATA[So I&#8217;ve been working on a 3D graphics project for school, and I&#8217;ve come across an inconvenience: while g++, the linux compiler, will happily let you declare a new multi-dimensional array with a variable as the size, Visual Studio (the MicroSoft compiler) complains that such a daunting task is too difficult &#8212; &#8220;I expect a [...]]]></description>
			<content:encoded><![CDATA[<p>So I&#8217;ve been working on a 3D graphics project for school, and I&#8217;ve come across an inconvenience: while g++, the <strong>linux</strong> compiler, will happily let you declare a new multi-dimensional array with a variable as the size, Visual Studio (the <strong>MicroSoft</strong> compiler) complains that such a daunting task is too difficult &#8212; &#8220;I expect a FIXED, STATIC size for these arrays!&#8221; it says.</p>
<p>For example:</p>
<pre class="brush: cpp;">
void blah(int width, int height) {
    unsigned char Array[height][width];
}
</pre>
<p>Seems logical, right?  Create a new array, with whatever width and height were passed to the function.  And, as I said, g++ will happily let you do this (well, maybe not <em>this</em> particular example, but you get the idea), but VS complains.</p>
<p>As such, and since I have to have a Windows binary to submit to the professor, I&#8217;ve ventured into the world of <strong>malloc</strong>.  Sounds like a villain&#8217;s name, doesn&#8217;t it?  For those who don&#8217;t know, <a href="http://www.elook.org/programming/c/malloc.html">malloc</a> is (one of?) C&#8217;s <strong>m</strong>emory <strong>alloc</strong>ation function(s) &#8212; give it the amount of memory you need, it&#8217;ll reserve that much memory and return the base address (in the form of a &#8220;void *&#8221;.  pfft.).  Of course, it&#8217;s not that simple, but that&#8217;s the basic idea.</p>
<p>To get our two-dimensional array with malloc, you need to get fancy with the looping.  For example:</p>
<pre class="brush: cpp;">
void blah(int width, int height) {
    unsigned char** Array = (unsigned char**)malloc(height*sizeof(unsigned char*));
    for (int i=0; i&lt;height ; i++) {
        Array[i] = (unsigned char*)malloc(width*sizeof(unsigned char));
    }
}
</pre>
<p>What a freakin&#8217; mess!  Instead of reading &#8220;create a height-by-width array&#8221;, this reads more like &#8220;eat up as much memory as you can&#8221;.  Yes, you have to semi-manually create each level of the &#8220;dynamic&#8221; array, all so you can conveniently use &#8220;Array[n][m]&#8221; later in your program.  Want a three-dimensional array (used to hold RGB images &#8212; Array[height][width][3])?</p>
<pre class="brush: cpp;">
void blah(int width, int height) {
    unsigned char*** Array = (unsigned char***)malloc(height*sizeof(unsigned char**));
    for (int i=0; i&lt;height ; i++) {
        Array[i] = (unsigned char**)malloc(width*sizeof(unsigned char*));
        for (int j=0; j&lt;width; j++) {
            Array[i][j] = (unsigned char*)malloc(3*sizeof(unsigned char));
        }
    }
}
</pre>
<p>And so on for each dimension you wish to add.  Truly hideous.  So many levels of pointers to keep track of, so many <em>stinking</em> loops!  There is such a better way <img src='http://techknack.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Instead of using unsightly code to allow the convenience of multiple subscripts, you could just as well create a width*height(*3), single-dimensional array, and use some simple math to get the proper offset.  Here are examples of up to three dimensions (I&#8217;ve actually used the three-dimension one in my program to load an image file, works perfectly):</p>
<pre class="brush: cpp;">
// One dimension -- easy enough:
unsigned char* OneDim = (unsigned char*)malloc(width*sizeof(unsigned char));
for (int i=0; i&lt;width ; i++) {
    OneDim[i];
}

// Two dimensions -- a little trickier:
unsigned char* TwoDim = (unsigned char*)malloc(width*height*sizeof(unsigned char));
for (int i=0; i&lt;height; i++) {
    for (int j=0; j&lt;width; j++) {
        // TwoDim[i][j] =
        TwoDim[i*width+j];
    }
}

// Three dimensions -- w00t, crazy!
unsigned char* ThreeDim = (unsigned char*)malloc(width*height*3*sizeof(unsigned char));
for (int i=0; i&lt;height; i++) {
    for (int j=0; j&lt;width; j++) {
        for (int k=0; k&amp;lt;3; k++) {
            // ThreeDim[i][j][k] =
            ThreeDim[(i*width+j)*3+k];
        }
    }
}
</pre>
<p>If I&#8217;m not mistaken, the recursive pattern for the subscript is &#8220;(other-loops)*max+counter&#8221;, starting from the innermost loop.  So three dimensions goes like this:</p>
<pre class="brush: plain;">
(other-loops)*3+k
((other-loops)*width+j)*3+k
(((other-loops)*height+i)*width+j)*3+k

no more loops, use &quot;0&quot;:

(((0)*height+i)*width+j)*3+k
((i)*width+j)*3+k
(i*width+j)*3+k
</pre>
<p>So, for a fourth loop &#8220;m&#8221; going from 0 to, say, 40, we would probably have:</p>
<pre class="brush: plain;">
((i*width+j)*3+k)*40+m
</pre>
<p>And so on, but who uses 4D arrays, anyways?</p>
<p><em>Disclaimers:<br />
&#8220;for (int i=0; &#8230;&#8221; syntax is, as far as I know, a C++ feature; in true C, you would have to declare &#8220;i&#8221; beforehand, then use it in the loop.<br />
When creating objects with malloc, be sure to <a href="http://www.elook.org/programming/c/free.html">free</a> the memory when you&#8217;re done with it; I refuse to be held responsible for memory leaks in your program.<br />
C library &#8220;stdlib.h&#8221; must be included to use these functions.<br />
Yes, you have to typecast malloc&#8217;s return value to whatever your data type is, unless your variable itself is a &#8220;void *&#8221;, but why would you need a pointer to nothing?<br />
For each level of the array in the first malloc example, you need as many &#8220;*&#8221; as you have levels left to create &#8212; three for the first level, two for the next, one for the last, etc.<br />
Strictly speaking, &#8220;sizeof(unsigned char)&#8221; translates to &#8220;1&#8243;, so it&#8217;s not necessary here; however, it is required to get the right size for other data types, in which case the hideous factor is no more reduced.<br />
I have not tested, nor plan on testing, the four-dimensional subscript example given above.  If it doesn&#8217;t work and you figure out how to make it work, feel free to post your solution <img src='http://techknack.net/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </em></p>
<img src="http://techknack.net/?ak_action=api_record_view&id=191&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/using-a-1d-array-like-a-2d-or-3d-array/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Torrent Management System with rTorrent and Bash</title>
		<link>http://techknack.net/torrent-management-system-with-rtorrent-and-bash/</link>
		<comments>http://techknack.net/torrent-management-system-with-rtorrent-and-bash/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 08:36:16 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[rtorrent]]></category>
		<category><![CDATA[torrent]]></category>
		<category><![CDATA[torrent management system]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=176</guid>
		<description><![CDATA[I do a fair amount of torrenting, mostly for TV shows.  A college student&#8217;s schedule doesn&#8217;t always allow for sitting in front of the TV on a certain night during a certain timeslot   .  Nor does it allow for micromanaging my torrents &#8212; making sure I have enough, but not too [...]]]></description>
			<content:encoded><![CDATA[<p>I do a fair amount of torrenting, mostly for TV shows.  A college student&#8217;s schedule doesn&#8217;t always allow for sitting in front of the TV on a certain night during a certain timeslot <img src='http://techknack.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .  Nor does it allow for micromanaging my torrents &#8212; making sure I have enough, but not too many, torrents running at a given time; making sure torrents are properly seeded once downloaded; making sure the files get moved to the right place on my external HDD (so XBMC can pull them over the network).  Just too much to make sure it all happens.</p>
<p>There are a lot of <acronym title="Graphical User interface">GUI</acronym> clients that claim to do a lot of this stuff, but I prefer the KDE-native KTorrent as my desktop client.  For a management system, though, the GUI is almost irrelevant &#8212; a set-it-and-forget-it system needs to sit in the background until called to the foreground, and rTorrent does this very nicely.  Coupled with an always-on-and-connected home server, some bash scripting, and the linux &#8220;screen&#8221; program, rTorrent is fully capable of automating torrent downloads.</p>
<p>In researching others&#8217; systems, I came across &#8220;<a href="http://www.stabellini.net/rtorrent-howto.txt">rTorrent as a download manager</a>&#8220;, a text file detailing what the author expected from his management system, and how he went about obtaining the desired results.  I also came across an <a href="http://libtorrent.rakshasa.no/wiki/RTorrentUserGuide">rTorrent and libtorrent user guide</a> on the <a href="http://libtorrent.rakshasa.no/">official rTorrent site</a>.  Unfortunately, there is little up-to-date, <i>detailed</i> info on all the options offered for rTorrent customization.</p>
<p>According to the first resource, the (initial) main goals of the <acronym title="Torrent Management System">TMS</acronym> are:</p>
<ol>
<li>Limit the number of concurrent active torrents</li>
<li>Queue and start inactive torrents</li>
<li>Move downloaded files to another directory and remove the associated .torrent file</li>
<li>Manage bandwidth usage to keep the DSL connection useful</li>
</ol>
<p>These are all well and good, and relatively simple to achieve with little bash scripting, but rTorrent is capable of more.  When a torrent is finished, I want to move it to another directory before I continue seeding.  When it&#8217;s done seeding, I want to move it to another directory, so I can know, simply by looking at directory contents, which files are completely done.  And, of course, I want to move the downloaded files to the appropriate directories.  So the complete list of TMS requirements is:</p>
<ol>
<li>Limit the number of concurrent active torrents</li>
<li>Queue and start inactive torrents</li>
<li>Move downloaded files to a second directory and continue to seed the torrent to a specific ratio</li>
<li>Move seeded files to a third directory and remove associated .torrent files</li>
<li>Manage bandwidth usage to keep the DSL connection useful</li>
<li>Move files from the final directory to the appropriate external locations</li>
</ol>
<p>The first two can be accomplished with rTorrent&#8217;s directory watching and a simple bash script.  The next three can be implemented solely within rTorrent.  And the final point can be implemented with a more complicated bash script that takes advantage of community torrent naming conventions.</p>
<p><a href='http://techknack.net/wp-content/uploads/rtorrent_dirs.png'><img src="http://techknack.net/wp-content/uploads/rtorrent_dirs.png" alt="" title="rtorrent_dirs" width="278" height="261" class="alignright size-full wp-image-177" /></a> First, the directory structure.  Let us assume that the base directory for torrent activity is <i>/torrents</i>.  Limiting torrents is a simple matter of making sure that rTorrent&#8217;s watched directory never contains more than N .torrent files, where N is our maximum.  This gives us two directories: <i>/torrents/watch</i> and <i>/torrents/loading</i>.  The <i>watch</i> directory is the one rTorrent will watch for torrents, and the <i>loading</i> directory will be a holding cell for inactive torrents.  Points 3 and 4 give us three more directories, <i>/torrents/active</i>, <i>/torrents/seeding</i>, and <i>/torrents/finished</i>.  These are for active, downloaded (seeding), and completely finished torrents, respectively.  Another directory to use is <i>/torrents/session</i>, for use with rTorrent&#8217;s session feature.  Finally, I have a hidden directory <i>/torrents/.archive</i> where I send copies of activated .torrent files.</p>
<p>Once the directory structure is in place, rTorrent needs to be told how to manage things.  This is done in the .rtorrent.rc file, which, by default, is in the initiating user&#8217;s home directory.  Here is the section of my .rtorrent.rc file that handles torrent management (make sure each command is on one line):</p>
<pre class="brush: plain;">
#************** Automagic Torrent Management  ****************#

# Maintain session info in /torrents/session
session=/torrents/session

# Drop .torrent files in /torrents/loading (or /torrents, if starttor can handle &quot;misguided&quot; files)

# Use &quot;starttor&quot; script on cronjob to keep /torrents/watch occupied with three or fewer .torrents

# Load torrents in &quot;watch&quot; directory (check every 5sec)
schedule = watch_directory,5,5,load_start=/torrents/watch/*.torrent

# Download torrents to &quot;active&quot; directory
directory = /torrents/active

# Move to &quot;seeding&quot; directory and seed when downloaded
on_finished = seed,&quot;execute=mv,-u,$d.get_base_path=,/torrents/seeding/ ;d.set_directory=/torrents/seeding/&quot;

# Close when seed ratio reached (check every 60sec)
schedule = ratio,60,60,&quot;close_on_ratio=110&quot;

# Move to &quot;finished&quot; on close (when both the file is downloaded and the ratio is reached)
on_close = move_fin,&quot;execute=mv,-u,$d.get_base_path=,/torrents/finished/ ;d.set_directory=/torrents/finished/&quot;

# Delete .torrent files in /torrents/watch when torrent is closed
on_close = remove_fin,&quot;execute=rm,$d.get_tied_to_file=&quot;

# Torrent is downloaded, seeded, and done with.  Use custom script to move to appropriate directory.

#*************************************************************#
</pre>
<p>All other &#8220;schedule&#8221; and &#8220;on_whatever&#8221; commands that were in the <a href="http://libtorrent.rakshasa.no/browser/trunk/rtorrent/doc/rtorrent.rc?rev=latest">example .rtorrent.rc file</a> are commented out.  This defines the session, watch, and active download directories; specifies that downloaded files should be moved to the seeding directory and seeded; specifies what ratio to stop a seeding torrent at; and specifies that completely finished torrents should be moved to the finished directory.  Getting finished files to be moved before seeding was fairly straightforward; in fact, there were already examples floating around the internet on how to do just that.  Getting the files moved when the torrent was finished was tricky.  All the examples I could find only showed &#8220;stop_on_ratio=&#8221; for the ratio schedule.  Unfortunately, this leaves the torrent sitting in rTorrent as &#8220;inactive&#8221;, and, were I to use the &#8220;on_stop&#8221; command, the torrent would be moved when Ctrl-D was pushed (which temporarily stops the torrent).  So I decided to try &#8220;close_on_ratio&#8221; instead, and that particular command happened to exist.  Thanks to this, the torrent is closed (and moved according to the following on_close command) when my 1.10 ratio is reached, freeing up space for the next torrent.  The only downside is if you are the original seed for a torrent (or are trying to seed a torrent beyond 1.10) and try to temporarily stop that torrent, it will be moved if the ratio is above 1.10.  Other commands in .rtorrent.rc (upload_rate and download_rate) allow bandwidth control.</p>
<p>Once rTorrent knows how to manage the torrents (and you can test this by starting rTorrent and dropping a torrent in the watch directory), you need to implement the &#8220;queuing system&#8221;.  Here is the &#8220;starttor&#8221; bash script that I use:</p>
<pre class="brush: bash;">
#!/bin/bash

# Root dir (for finding &quot;misguided&quot; torrents)
root=&quot;/torrents&quot;
# Loading dir (for inactives)
loading=&quot;/torrents/loading&quot;
# Watching dir (for actives)
watch=&quot;/torrents/watch&quot;
# Archive dir - leave blank (archive=&quot;&quot;) if you don't use one
archive=&quot;/torrents/.archive&quot;
# max # torrents at once
N=3

# max-1 for comparisons
N=$(($N-1))

# Move all &quot;misguided&quot; torrents (thrown into the root dir) to the &quot;loading&quot; dir
misguided=`ls &quot;$root&quot; | grep .*\.torrent | replace &quot; &quot; &quot;~&quot;`
for torrent in $misguided; do
    torrent=`echo $torrent | replace &quot;~&quot; &quot; &quot;`
    # Make all .torrent files rw/r/r
    chmod 644 &quot;$root/$torrent&quot;
    mv &quot;$root/$torrent&quot; &quot;$loading/&quot;
done

# If N or more active torrents, don't do anything
active=`ls &quot;$watch&quot; | grep .*\.torrent | grep &quot;.*&quot; -c`
if [ $active -gt $N ]; then
    exit 0;
fi

# If no inactive torrents, do nothing
inactive=`ls &quot;$loading&quot; | grep .*\.torrent | grep &quot;.*&quot; -c`
if [ $inactive -eq 0 ]; then
    exit 0;
fi

# While we have inactive torrents and less than 3 active, copy over inactives
tostart=`ls &quot;$loading&quot; | grep .*\.torrent | replace &quot; &quot; &quot;~&quot;`
for torrent in $tostart; do
    torrent=`echo &quot;$loading/$torrent&quot; | replace &quot;~&quot; &quot; &quot;`
    active=`ls &quot;$watch&quot; | grep .*\.torrent | grep &quot;.*&quot; -c`
    if [ $active -gt $N ]; then
        exit 0;
    fi
    if [ -n $archive ]; then
        cp &quot;$torrent&quot; &quot;$archive/&quot;
    fi
    mv &quot;$torrent&quot; &quot;$watch/&quot;
done
</pre>
<p>This script moves any stray torrents from the root directory (the easiest place to drop them) to the loading directory; I refer to these as &#8220;misguided&#8221; torrents, since they are not in the main loading directory.  It then checks for the number of active torrents; if the number is greater than or equal to the max, the script exits, doing nothing.  If there&#8217;s room for more, it checks for any torrents in the loading directory.  If there are torrents there, it will move them, one at a time, into the watch directory, until the max is reached.  If the archive variable is set, it will also save a copy to the specified directory.  You can use this script with cron; I use this line in root&#8217;s crontab to run it every ten minutes:</p>
<pre class="brush: plain;">
*/10 * * * * /home/andrew/bin/starttor
</pre>
<p>Moving the finished files to their appropriate places is more complicated.  Basically, you have to write a script that takes into account the common layout of filenames as well as your specific organizational directory tree.  For example, I like to download TV shows.  My directory structure is TV &gt; Show Name &gt; Season #.  Most TV torrent files follow the conventional naming scheme of TV.Show.Name.S01E03.Episode.Name.Release.Group.avi.  My script recursively goes through all the .avi files in the <i>finished</i> directory, for each file pulling out everything up to the season number (in this case, &#8220;TV.Show.Name.S01&#8243;).  It then splits it at the S##, extracting the show name and season number.  It then replaces all periods, underscores, and dashes in the show name with spaces, and reduces multiple consecutive spaces to one space each.  Once the show name is prepped, the script checks if the directory &#8220;TV Show Name&#8221; exists in the TV directory.  If it does, it checks for &#8220;Season #&#8221; (if that doesn&#8217;t exist, it checks for &#8220;Season#&#8221;, without the space, just in case).  If that exists, the file is moved to that Season directory.  If not, the file is left alone, for me to move manually if I need to.  This leaves other, non-TV torrents in the finished directory for me to work with later.  I also have this script on cron, but it is set to run every hour.</p>
<p>RTorrent makes building a TMS easy, as long as you know what settings to use.  To really automate the whole thing, I could add a script which daily (or weekly) checks various RSS feeds for new torrents of shows I like, but I haven&#8217;t gotten that far yet &#8212; I&#8217;m still manually hunting down my shows.  Since copying and pasting the file contents I&#8217;ve given is not ideal, copies of the files I use are <a href="/examples/rtorrent/">available for download</a>, just be sure to rename and chmod them as appropriate.</p>
<p>If you feel I left out any details, feel free to ask questions in the comments, and I&#8217;ll answer to the best of my ability.</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=176&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/torrent-management-system-with-rtorrent-and-bash/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Auto-Update Sun Map Wallpaper in KDE4</title>
		<link>http://techknack.net/auto-update-sun-map-wallpaper-in-kde4/</link>
		<comments>http://techknack.net/auto-update-sun-map-wallpaper-in-kde4/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 19:04:40 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[desktop]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=169</guid>
		<description><![CDATA[Yesterday, LifeHacker posted an article on setting up an auto-rotate wallpaper in Gnome.  Now, KDE4 comes with this functionality out of the box &#8211; just point the desktop configuration to an image folder, and it will rotate the images in user-specified intervals (with a minimum of one hour).  However, one comment by joelena [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://techknack.net/wp-content/uploads/worldmap.png'><img src="http://techknack.net/wp-content/uploads/worldmap.png" alt="" title="" width="300" height="166" class="size-full wp-image-170" /></a>Yesterday, LifeHacker posted an article on <a href="http://lifehacker.com/400505/rotate-desktop-backgrounds-in-ubuntu">setting up an auto-rotate wallpaper in Gnome</a>.  Now, KDE4 comes with this functionality out of the box &#8211; just point the desktop configuration to an image folder, and it will rotate the images in user-specified intervals (with a minimum of one hour).  However, <a href="http://lifehacker.com/400505/rotate-desktop-backgrounds-in-ubuntu#c7274862">one comment by joelena</a> caught my interest.  Joelena mentioned having found a way to display a &#8220;<a href="http://www.opentopia.com/images/cams/world_sunlight_map_rectangular.jpg">sun map</a>&#8221; as a wallpaper using a scheduled wget command.</p>
<p>Apparently, Gnome will automatically detect changes in the wallpaper image file, and update the desktop accordingly.  No joy with KDE4 &#8211; apparently the devs assume we&#8217;ll never change the image <img src='http://techknack.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  .  Fortunately, there&#8217;s a way to &#8220;trick&#8221; the KDE4 wallpaper rotator into updating the wallpaper with the latest sun map image.</p>
<p>First, create a folder to contain the sun map images, I created /usr/share/wallpapers/worldmap .  Next, setup a cron job to automatically pull the updated image.  Run &#8220;sudo crontab -e&#8221; in a terminal.  This will start you editing root&#8217;s cron file.  Paste the following as it&#8217;s own line in the cron file (Shift+Insert usually acts as paste for CLI editors):</p>
<pre class="brush: plain;">
10 * * * * wget http://www.opentopia.com/images/cams/world_sunlight_map_rectangular.jpg -O- | convert - -scale 1440x900 /usr/share/wallpapers/worldmap/worldmap.png &amp;&amp; cp /usr/share/wallpapers/worldmap/worldmap.png /usr/share/wallpapers/worldmap/worldmap1.png
</pre>
<p>Be sure that it&#8217;s all on one line, and be sure to edit the -scale option for the convert command to match your own screen resolution, and the directory paths to match your directory.  Save and exit.  This command will pull the sun map image from the server that maintains it, and run it through the convert command to rescale it and convert it to a PNG image.  Then, it will copy the output file to a file in the same directory with a different name.  The cron options (the &#8220;10 * * * *&#8221;) specify that the command will be run ten minutes after every hour (apparently the map image is updated shortly after every hour).</p>
<p>Alternatively, you can copy and paste the following into a plain text file, add the proper permissions to make the file executable (chmod +x file), and use whatever scheduling software you like to run the script shortly after every hour:</p>
<pre class="brush: bash;">
#!/bin/bash

dir=&quot;/usr/share/wallpapers/worldmap&quot;
file=&quot;worldmap&quot;
file2=&quot;worldmap1&quot;
format=&quot;png&quot;
scale=&quot;1440x900&quot;

wget http://www.opentopia.com/images/cams/world_sunlight_map_rectangular.jpg -O- | convert - -scale ${scale} ${dir}/${file}.${format}
cp ${dir}/${file}.${format} ${dir}/${file2}.${format}
</pre>
<p>This script does the same thing, but in a more easily customizable form.</p>
<p>Once you have the script setup, run it once to get the initial files, and point KDE4&#8217;s wallpaper slideshow to the directory containing the two files.  It will loop through the two files (both of which are updated every hour), constantly updating your wallpaper with the changes.</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=169&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/auto-update-sun-map-wallpaper-in-kde4/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Hosting a Website: The Server</title>
		<link>http://techknack.net/hosting-a-website-the-server/</link>
		<comments>http://techknack.net/hosting-a-website-the-server/#comments</comments>
		<pubDate>Tue, 12 Aug 2008 15:04:57 +0000</pubDate>
		<dc:creator>eternicode</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://techknack.net/?p=158</guid>
		<description><![CDATA[A server, in the basic sense, is a computer which runs a program (also called a server or server application) that provides a service to other computers.  This could include an HTTP (or web) server, a DNS name server, a mail server, a VNC server, an SSH server, an FTP server &#8212; and many, [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href='http://en.wikipedia.org/wiki/Server_(computing)'>server</a>, in the basic sense, is a computer which runs a program (also called a server or server application) that provides a service to other computers.  This could include an HTTP (or web) server, a DNS name server, a mail server, a VNC server, an SSH server, an FTP server &#8212; and many, many others.  A server can run any number of server applications, provided it has the resources to run them all simultaneously.  Each program binds and listens to a distinct port on the computer running it, usually the standard port for whatever service it is providing (for example, 22 for SSH, or 80 for HTTP).  When another computer wants to use that service, it sends a message to the server, on the appropriate port, to request service from the program.  The program then sends a response, establishing a connection between the two computers; the service is rendered, and the connection is severed.</p>
<p>To host your own website, you need a computer with an HTTP server, and a decent (not dialup) always-on internet connection.  A spare computer (used as a &#8220;dedicated server&#8221;) with, say, a 333MHz processor and 256MB memory is plenty sufficient to serve a low-traffic website, especially if you put an <a href="http://www.ubuntu.com/products/whatisubuntu/serveredition">operating system</a> with <a href="https://help.ubuntu.com/community/Installation/SystemRequirements">low resource requirements</a> on it.  If you have a &#8220;modern&#8221; home computer (usually 1GHz+ and 512MB+), you could even install the web server on that machine, provided you always leave the machine running.  Hard drive requirements are very small as well; if you are using a dedicated server, you could use a 10GB hard drive and have more than enough space for your website.</p>
<p>Once you have a machine designated as your server, you need to set it up.  If you have a dedicated server, and you plan on using the existing operating system, make sure that no unnecessary programs start running at startup.  Once the operating system is prepped (or installed, as the case may be; your home computer can most likely be run normally), you need to install the web server.</p>
<p>In terms of web servers, <a href="http://www.apache.org/">Apache</a> is the <a href="http://news.netcraft.com/archives/web_server_survey.html">most widely used</a>.  And it&#8217;s <a href="http://www.apache.org/foundation/licence-FAQ.html#WhatDoesItMEAN">free</a>.  And it&#8217;s bundled with <a href="http://www.ubuntu.com/products/whatisubuntu/serveredition">Ubuntu server edition</a>, should you choose to add it during installation.  These reasons and more make Apache a good web server to start with (and, ultimately, stick with).  Once you have Apache installed, it needs to be setup to know what files to serve as what website.  Check out the <a href="http://httpd.apache.org/docs/1.3/vhosts/">Apache Virtual Host documentation</a> for details on setting up individual websites.</p>
<img src="http://techknack.net/?ak_action=api_record_view&id=158&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://techknack.net/hosting-a-website-the-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

