<?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>arteme.fi</title>
	<atom:link href="http://www.arteme.fi/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.arteme.fi</link>
	<description>python, web programming and all things unrelated</description>
	<lastBuildDate>Fri, 16 Apr 2010 13:39:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Kill That Hanging SSH!</title>
		<link>http://www.arteme.fi/2010/03/29/kill-that-hanging-ssh/</link>
		<comments>http://www.arteme.fi/2010/03/29/kill-that-hanging-ssh/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 15:12:44 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://g5.arteme.fi/wordpress/?p=72</guid>
		<description><![CDATA[

EDIT: The scipt below was updated on 2010-04-08 to identify the
correct xterm-ssh pair based on the X window id.
I spend a lot of time working remotely, ssh-ing to hosts from places
with bad wireless connection or glitchy firewalls. When an ssh session
hangs, it is bad enough. Trying to locate one dead ssh amid a dozen
live ones [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="kill-that-hanging-ssh">
<blockquote><p>
<strong>EDIT:</strong> The scipt below was updated on 2010-04-08 to identify the<br />
correct <tt class="docutils literal">xterm</tt>-<tt class="docutils literal">ssh</tt> pair based on the X window id.</p></blockquote>
<p>I spend a lot of time working remotely, <tt class="docutils literal">ssh</tt>-ing to hosts from places<br />
with bad wireless connection or glitchy firewalls. When an <tt class="docutils literal">ssh</tt> session<br />
hangs, it is bad enough. Trying to locate one dead <tt class="docutils literal">ssh</tt> amid a dozen<br />
live ones is tedious. It grows into a major headache if you need to do<br />
that several times a hour. So, I have a dead <tt class="docutils literal">ssh</tt> in an <tt class="docutils literal">xterm</tt><br />
window, how do I kill it? Moreover, how do I automate the process?</p>
<p>Luckily, most applications nowadays export the process id, controlling a<br />
particular X window, as a property of that window and <a class="reference external" href="http://www.xfree86.org/current/xprop.1.html">xprop</a> is a tool<br />
that can help us query that.</p>
<p>Run <a class="reference external" href="http://www.xfree86.org/current/xprop.1.html">xprop</a> as follows and click on the window of interest:</p>
<pre class="literal-block">arteme@book:~$ xprop _NET_WM_PID
_NET_WM_PID(CARDINAL) = 17843
</pre>
<p>Knowing the process id of the terminal we can track down the <tt class="docutils literal">ssh</tt> process<br />
that runs within:</p>
<pre class="literal-block">arteme@book:~$ pstree -Ap 17843
xterm(17843)---bash(17889)---ssh(21687)
</pre>
<p>There&#8217;s a process id that can be killed.</p>
<p>Half the work is done and it seems that it can be easily rolled into a shell<br />
script, but if you did, you would notice that if you started an xterm within<br />
an xterm and an ssh within that, pstree output would look like:</p>
<pre class="literal-block">arteme@book:~$ pstree -Alp 3443
xterm(3443)---bash(3447)---xterm(3705)---bash(3706)---ssh(9612)
</pre>
<p>If you start the second xterm in background and start ssh in both of them,<br />
the output becomes even more chaotic:</p>
<pre class="literal-block">arteme@book:~$ pstree -Alp 3444
xterm(3444)---bash(3446)-+-ssh(12549)
                         `-xterm(12508)---bash(12509)---ssh(12540)
</pre>
<p>So, what to kill?</p>
<p>Luckily, you can trace the <tt class="docutils literal">ssh</tt> process back to the terminal window it is<br />
running in by it&#8217;s window id. Using <a class="reference external" href="http://www.xfree86.org/current/xprop.1.html">xprop</a> we can find out the window id<br />
of the terminal, which is passed in the <tt class="docutils literal">WINDOWID</tt> variable to the<br />
processes started within. So, for the two <tt class="docutils literal">xterm</tt>s above with their<br />
<tt class="docutils literal">ssh</tt>:</p>
<pre class="literal-block">arteme@book:~$ xprop -f WM_CLIENT_LEADER '32c' ' = $0\n' WM_CLIENT_LEADER
WM_CLIENT_LEADER(WINDOW) = 79691810
arteme@book:~$ cat /proc/12549/environ | tr '\0' '\n' | grep WINDOWID
WINDOWID=79691810
</pre>
<p>and:</p>
<pre class="literal-block">arteme@book:~$ xprop -f WM_CLIENT_LEADER '32c' ' = $0\n' WM_CLIENT_LEADER
WM_CLIENT_LEADER(WINDOW) = 77594658
arteme@book:~$ cat /proc/12540/environ | tr '\0' '\n' | grep WINDOWID
WINDOWID=77594658
</pre>
<p><em>By default, &#8220;xprop&#8221; will return the window id as in hex, so the &#8220;-f &#8230;&#8221;<br />
argument is necessary to override that and ease the comparison, since the<br />
&#8220;WINDOWID&#8221; environment variable is in decimal.</em></p>
<p>Note, however, that if you run <tt class="docutils literal">screen</tt> with multiple ssh instances within,<br />
the environment of those <tt class="docutils literal">ssh</tt> processes contains the <tt class="docutils literal">WINDOWID</tt> of the<br />
original xterm they were started in, if any. That information is not reliable<br />
as it if you detached from the screen in one <tt class="docutils literal">xterm</tt> and attached to it in<br />
another one, the <tt class="docutils literal">WINDOWID</tt> will no longer be correct. Luckily, one can<br />
identify a screen session by the presence of the <tt class="docutils literal">STY</tt> variable in the<br />
environment&#8230;</p>
<p>Now this all can be rolled into a shell script:</p>
<div class="highlight">
<pre><span class="c">#!/bin/bash</span>

<span class="c"># Get the X terminal window properties and extract window id and process id</span>
<span class="nv">prop</span><span class="o">=</span><span class="sb">`</span>xprop -notype -f WM_CLIENT_LEADER <span class="s1">'32c'</span> <span class="s1">' = $0\n'</span> <span class="se">\</span>
            WM_CLIENT_LEADER <span class="se">\</span>
            _NET_WM_PID<span class="sb">`</span>

<span class="nv">wid</span><span class="o">=</span><span class="sb">`</span><span class="nb">echo</span> <span class="nv">$prop</span> | sed -n <span class="s1">'s/.*WM_CLIENT_LEADER = \([0-9]\{1,\}\).*/\1/p'</span><span class="sb">`</span>
<span class="nv">pid</span><span class="o">=</span><span class="sb">`</span><span class="nb">echo</span> <span class="nv">$prop</span> | sed -n <span class="s1">'s/.*NET_WM_PID = \([0-9]\{1,\}\).*/\1/p'</span><span class="sb">`</span>

<span class="c"># Exit if any of the data was missing</span>
<span class="o">[</span> -z <span class="s2">"$wid"</span> -o -z <span class="s2">"$pid"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">exit</span>

<span class="c"># Get the process tree and extract the ssh process id from there</span>
<span class="nv">ssh</span><span class="o">=</span><span class="sb">`</span>pstree -Apl <span class="nv">$pid</span> | sed -n <span class="s1">'s/.*ssh(\([0-9]\{1,\}\))/\1/p'</span><span class="sb">`</span>

<span class="c"># Filter ssh windows so that they do not belong to a screen session and</span>
<span class="c"># do run in the X terminal the user clicked on</span>
<span class="k">for </span>i in <span class="nv">$ssh</span>; <span class="k">do</span>
<span class="k">    </span><span class="nv">sty</span><span class="o">=</span><span class="sb">`</span>cat /proc/<span class="nv">$i</span>/environ | tr <span class="s1">'\0'</span> <span class="s1">'\n'</span> | grep <span class="s1">'^STY'</span><span class="sb">`</span>
    <span class="nv">window</span><span class="o">=</span><span class="sb">`</span>cat /proc/<span class="nv">$i</span>/environ | tr <span class="s1">'\0'</span> <span class="s1">'\n'</span> |<span class="se">\</span>
            sed -n <span class="s1">'s/WINDOWID=\(.*\)/\1/p'</span><span class="sb">`</span>

    <span class="o">[</span> -n <span class="s2">"$sty"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="k">continue</span>
    <span class="o">[</span> <span class="s2">"$wid"</span> !<span class="o">=</span> <span class="s2">"$window"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="k">continue</span>

<span class="k">    </span><span class="nv">tokill</span><span class="o">=</span><span class="s2">"$tokill $i"</span>
<span class="k">done</span>

<span class="c"># Exit if there's nothing to kill</span>
<span class="o">[</span> -z <span class="s2">"$tokill"</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">exit</span>

<span class="c"># Kill the process</span>
<span class="nb">kill</span> -9 <span class="nv">$tokill</span>
</pre>
</div>
<p>Grab that as a bash script, <a class="reference external" href="http://www.arteme.fi/wordpress/wp-content/uploads/2010/04/kill-that-ssh.sh">kill_that_ssh.sh</a>. Furthermore, you can add it<br />
to your quick-launch bar to never have to let go of your mouse when reaching<br />
for the tool:</p>
<p><img alt="http://g5.arteme.fi/wordpress/wp-content/uploads/2010/03/kill-that-ssh.png" src="http://g5.arteme.fi/wordpress/wp-content/uploads/2010/03/kill-that-ssh.png">
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2010/03/29/kill-that-hanging-ssh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Beginnings</title>
		<link>http://www.arteme.fi/2010/03/29/new-beginnings/</link>
		<comments>http://www.arteme.fi/2010/03/29/new-beginnings/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 14:46:24 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://g5.arteme.fi/wordpress/?p=69</guid>
		<description><![CDATA[
In an attempt to clear out my head, I am back with things to post. Starting with a new iteration, you revise the tools and processes that have been holding you back. With this I have to say &#8220;good bye!&#8221; to trac that has been serving me faithfully as a platform for the site and [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="new-beginnings">
<p>In an attempt to clear out my head, I am back with things to post. Starting with a new iteration, you revise the tools and processes that have been holding you back. With this I have to say &#8220;good bye!&#8221; to <a class="reference external" href="http://trac.edgewall.org/">trac</a> that has been serving me faithfully as a platform for the site and say &#8220;hello!&#8221; to a shiny new <a class="reference external" href="http://wordpress.org/">Wordpress</a> installation. This is ironic, since I moved to trac from Wordpress long time ago. Unfortunately, trac&#8217;s blogging and page infrastructure did not advance in the direction I would have liked to see it go, while Wordpress did. The latest addition that won me over was the <a class="reference external" href="http://xdissent.com/projects/wordprest/">ReST plug-in</a> for Wordpress that I am happily using now- While I still frown upon running a MySQL server to power this tiny site, that is the way it is going to be for now.</p>
<p>I will be slowly migrating the content of the old site over to the new one and the old blog entries will eventually find their way to the new site too.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2010/03/29/new-beginnings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django CherryPy Development Server and Serving Static Files</title>
		<link>http://www.arteme.fi/2009/02/26/django-cherrypy-dev-server-and-static-files/</link>
		<comments>http://www.arteme.fi/2009/02/26/django-cherrypy-dev-server-and-static-files/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 12:34:34 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[cherrypy]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[static]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://www.arteme.fi/?p=91</guid>
		<description><![CDATA[

Introduction
Django web framework is famous for how easy it is to start developing
application with it. An installation of python and django is all you need to
get busy. Django provides you with all the essential gears and gadgets
including a simple development web server that you can use to run the
application you are developing, while you are [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="django-cherrypy-development-server-and-serving-static-files">
<div class="section" id="introduction">
<h2>Introduction</h2>
<p><a class="reference external" href="http://djangoproject.com">Django web framework</a> is famous for how easy it is to start developing<br />
application with it. An installation of python and django is all you need to<br />
get busy. Django provides you with all the essential gears and gadgets<br />
including a simple development web server that you can use to run the<br />
application you are developing, while you are developing it.</p>
<p>However, as your project grows more and more complex, you will discover the<br />
limitations of the development server. The first one you are most likely to<br />
face is the inability to serve static files (like site-specific media files).<br />
To be frank, it is not so much an inability but reluctance &#8212; there is a<br />
<a class="reference external" href="http://docs.djangoproject.com/en/dev/howto/static-files/">well-documented recepie</a> of how to set up serving of static files, but it<br />
has &#8220;do not use in production&#8221; written all over it. In fact, any use of the<br />
development server in production environment is discouraged, as the following<br />
disclaimer found in the documentation promptly states:</p>
<blockquote><p>
DO NOT USE THIS SERVER IN A PRODUCTION SETTING. It has not gone through<br />
security audits or performance tests. (And that&#8217;s how it&#8217;s gonna stay.<br />
We&#8217;re in the business of making Web frameworks, not Web servers, so<br />
improving this server to be able to handle a production environment is<br />
outside the scope of Django.)</p></blockquote>
<p>Another, more serious limitation is its inherent single-threadedness. If you<br />
are developing any kind of AJAX application that might need to have more than<br />
one connection to the web server at any point in time you will run into<br />
problems &#8212; the development server will only start processing the second<br />
request once it&#8217;s done with processing the first one. Recently, the topic of<br />
a more advanced, multi-threaded development server has been coming up in the<br />
mailing lists more and more often. All the pleads to improve the default dev.<br />
server were met with &#8220;won&#8217;t fix&#8221; comments pointing out that it is extremely<br />
easy to hookup a custom <a class="reference external" href="http://www.cherrypy.org">CherryPy</a> server to the django WSGI request handler<br />
achieving this functionality.</p>
</div>
<div class="section" id="basic-cherrypy-setup">
<h2>Basic CherryPy setup</h2>
<p>As of version 1.0, Django provides an interface for adding <a class="reference external" href="http://docs.djangoproject.com/en/dev/howto/custom-management-commands/">custom management<br />
commands</a>, which can be used to integrate Django with CherryPy.<br />
<a class="reference external" href="http://oebfare.com/blog/2008/nov/03/writing-custom-management-command/">http://oebfare.com/blog/2008/nov/03/writing-custom-management-command/</a> is a<br />
good article on how to integrate the two, but for the sake of clarity and<br />
completeness let&#8217;s reiterate.</p>
<p><strong>A word of warning:</strong> The code presented here is for CherryPy<br />
<a class="reference external" href="http://www.cherrypy.org/wiki/WhatsNewIn31">version 3.1</a> since it uses <tt class="docutils literal">WSGIPathInfoDispatcher</tt> class. It may be<br />
possible to back-port it to version 3.0, but I make no guaranties.</p>
<p>We will add a &#8220;<tt class="docutils literal">runcherrypy</tt>&#8221; command, so that the server is started as:</p>
<pre class="literal-block">./manage.sh runcherrypy [-h &lt;address&gt;] [-p &lt;port&gt;]
</pre>
<p>The following file tree will be added to the project directory:</p>
<pre class="literal-block">devserver/
 |-- __init__.py
 `-- management/
      |-- __init__.py
      `-- commands/
           |-- __init__.py
           `-- runcherrypy.py
</pre>
<p>where <tt class="docutils literal">runcherrypy.py</tt> is as follows:</p>
<div class="highlight">
<pre><span class="kn">from</span> <span class="nn">django.core.management.base</span> <span class="kn">import</span> <span class="n">BaseCommand</span>
<span class="kn">from</span> <span class="nn">django.core.handlers.wsgi</span> <span class="kn">import</span> <span class="n">WSGIHandler</span>

<span class="kn">from</span> <span class="nn">cherrypy.wsgiserver</span> <span class="kn">import</span> <span class="n">CherryPyWSGIServer</span>

<span class="kn">from</span> <span class="nn">optparse</span> <span class="kn">import</span> <span class="n">OptionParser</span><span class="p">,</span> <span class="n">make_option</span>

<span class="k">class</span> <span class="nc">Command</span><span class="p">(</span> <span class="n">BaseCommand</span> <span class="p">):</span>

    <span class="n">option_list</span> <span class="o">=</span> <span class="n">BaseCommand</span><span class="o">.</span><span class="n">option_list</span> <span class="o">+</span> <span class="p">(</span>
            <span class="n">make_option</span><span class="p">(</span> <span class="s">"-h"</span><span class="p">,</span> <span class="s">"--host"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"host"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">"127.0.0.1"</span> <span class="p">),</span>
            <span class="n">make_option</span><span class="p">(</span> <span class="s">"-p"</span><span class="p">,</span> <span class="s">"--port"</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s">"port"</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="mf">8000</span> <span class="p">),</span>
            <span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle</span><span class="p">(</span> <span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span> <span class="p">):</span>

        <span class="n">app</span> <span class="o">=</span> <span class="n">WSGIHandler</span><span class="p">()</span>
        <span class="n">server</span> <span class="o">=</span> <span class="n">CherryPyWSGIServer</span><span class="p">(</span> <span class="p">(</span><span class="n">options</span><span class="p">[</span><span class="s">'host'</span><span class="p">],</span> <span class="n">options</span><span class="p">[</span><span class="s">'port'</span><span class="p">]),</span>
                                     <span class="n">app</span> <span class="p">)</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="n">server</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
        <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
            <span class="n">server</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">create_parser</span><span class="p">(</span> <span class="bp">self</span><span class="p">,</span> <span class="n">prog</span><span class="p">,</span> <span class="n">subcommand</span> <span class="p">):</span>
        <span class="sd">"""</span>
<span class="sd">        Create and return the ``OptionParser`` which will be used to</span>
<span class="sd">        parse the arguments to this command.</span>
<span class="sd">        """</span>
        <span class="k">return</span> <span class="n">OptionParser</span><span class="p">(</span> <span class="n">prog</span><span class="o">=</span><span class="n">prog</span><span class="p">,</span>
                             <span class="n">usage</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">usage</span><span class="p">(</span><span class="n">subcommand</span><span class="p">),</span>
                             <span class="n">version</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">get_version</span><span class="p">(),</span>
                             <span class="n">option_list</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">option_list</span><span class="p">,</span>
                             <span class="n">conflict_handler</span><span class="o">=</span><span class="s">"resolve"</span> <span class="p">)</span>
</pre>
</div>
<p>Now, add <tt class="docutils literal">'devserver'</tt> to your <tt class="docutils literal">settings.py</tt> and you&#8217;re ready to go! If<br />
you have set up your static file serving in django, <a class="reference external" href="http://docs.djangoproject.com/en/dev/howto/static-files/">as specified earlier</a>,<br />
everything should &#8220;just work&#8221;. But why go through the network of django<br />
resolvers just to arrive at basic static page serving if you can do it on<br />
the CherryPy side?</p>
</div>
<div class="section" id="serving-static-files">
<h2>Serving static files</h2>
<p>A careful observer might notice that django actually serves the admin<br />
interface static content quite happily. That is done by<br />
<cite>django.core.servers.basehttp.AdminMediaHandler class</cite>. Steven Wilcox<br />
at <a class="reference external" href="http://www.devpicayune.com">http://www.devpicayune.com</a> has already taken <tt class="docutils literal">AdminMediaHandler</tt> into<br />
use in <a class="reference external" href="http://www.devpicayune.com/entry/hosting-django-with-cherrypy-wsgi-server">his article on django/CherryPy integration</a>. If only one could use<br />
<tt class="docutils literal">AdminMediaHandler</tt> to serve static content outside of the<br />
<tt class="docutils literal"><span class="pre">.../contrib/admin/media/</span></tt> directory&#8230;</p>
<p>Why not? Here is a modified version of <tt class="docutils literal">AdminMediaHandler</tt> applicable for<br />
serving any static content. We will put it to <tt class="docutils literal">devserver/mediahandler.py</tt>:</p>
<div class="highlight">
<pre><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">stat</span><span class="o">,</span> <span class="nn">mimetypes</span>
<span class="kn">import</span> <span class="nn">django</span>
<span class="kn">from</span> <span class="nn">django.utils.http</span> <span class="kn">import</span> <span class="n">http_date</span>
<span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>

<span class="k">class</span> <span class="nc">MediaHandler</span><span class="p">(</span> <span class="nb">object</span> <span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span> <span class="bp">self</span><span class="p">,</span> <span class="n">media_root</span> <span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">media_root</span> <span class="o">=</span> <span class="n">media_root</span>

    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span> <span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span> <span class="p">):</span>

        <span class="k">def</span> <span class="nf">done</span><span class="p">(</span> <span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">output</span> <span class="p">):</span>
            <span class="n">start_response</span><span class="p">(</span> <span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="p">)</span>
            <span class="k">return</span> <span class="n">output</span>

        <span class="n">path_info</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s">'PATH_INFO'</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">path_info</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">'/'</span><span class="p">:</span>
            <span class="n">path_info</span> <span class="o">=</span> <span class="n">path_info</span><span class="p">[</span><span class="mf">1</span><span class="p">:]</span>

        <span class="n">file_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span> <span class="bp">self</span><span class="o">.</span><span class="n">media_root</span><span class="p">,</span> <span class="n">path_info</span> <span class="p">)</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span> <span class="n">file_path</span> <span class="p">):</span>
            <span class="n">status</span> <span class="o">=</span> <span class="s">'404 NOT FOUND'</span>
            <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">'Content-type'</span><span class="p">:</span> <span class="s">'text/plain'</span><span class="p">}</span>
            <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s">'Page not found: </span><span class="si">%%s</span><span class="s">'</span> <span class="o">%%</span> <span class="n">file_path</span><span class="p">]</span>
            <span class="k">return</span> <span class="n">done</span><span class="p">(</span> <span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">output</span> <span class="p">)</span>

        <span class="k">try</span><span class="p">:</span>
            <span class="n">fp</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span> <span class="n">file_path</span><span class="p">,</span> <span class="s">'rb'</span> <span class="p">)</span>
        <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
            <span class="n">status</span> <span class="o">=</span> <span class="s">'401 UNAUTHORIZED'</span>
            <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">'Content-type'</span><span class="p">:</span> <span class="s">'text/plain'</span><span class="p">}</span>
            <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s">'Permission denied: </span><span class="si">%%s</span><span class="s">'</span> <span class="o">%%</span> <span class="n">file_path</span><span class="p">]</span>
            <span class="k">return</span> <span class="n">done</span><span class="p">(</span> <span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">output</span> <span class="p">)</span>

        <span class="c"># This is a very simple implementation of conditional GET with</span>
        <span class="c"># the Last-Modified header. It makes media files a bit speedier</span>
        <span class="c"># because the files are only read off disk for the first request</span>
        <span class="c"># (assuming the browser/client supports conditional GET).</span>

        <span class="n">mtime</span> <span class="o">=</span> <span class="n">http_date</span><span class="p">(</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">file_path</span><span class="p">)[</span><span class="n">stat</span><span class="o">.</span><span class="n">ST_MTIME</span><span class="p">]</span> <span class="p">)</span>
        <span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">'Last-Modified'</span><span class="p">:</span> <span class="n">mtime</span><span class="p">}</span>
        <span class="k">if</span> <span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'HTTP_IF_MODIFIED_SINCE'</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="o">==</span> <span class="n">mtime</span><span class="p">:</span>
            <span class="n">status</span> <span class="o">=</span> <span class="s">'304 NOT MODIFIED'</span>
            <span class="n">output</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">status</span> <span class="o">=</span> <span class="s">'200 OK'</span>
            <span class="n">mime_type</span> <span class="o">=</span> <span class="n">mimetypes</span><span class="o">.</span><span class="n">guess_type</span><span class="p">(</span><span class="n">file_path</span><span class="p">)[</span><span class="mf">0</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">mime_type</span><span class="p">:</span>
                <span class="n">headers</span><span class="p">[</span><span class="s">'Content-Type'</span><span class="p">]</span> <span class="o">=</span> <span class="n">mime_type</span>
            <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">()]</span>
            <span class="n">fp</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

        <span class="k">return</span> <span class="n">done</span><span class="p">(</span> <span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">output</span> <span class="p">)</span>
</pre>
</div>
<p>CherryPy version 3.1 provides <tt class="docutils literal">WSGIPathInfoDispatcher</tt> class which exposes<br />
an interface to run multiple WSGI applications side-by-side, distinguished<br />
by request path. We will utilize this to set up three applications:</p>
<ul class="simple">
<li>Django framework project, served by <tt class="docutils literal">WSGIHandler</tt>: this will be placed<br />
at webserver root, &#8216;/&#8217;.</li>
<li>Site media, served by <tt class="docutils literal">MediaHandler</tt>: project settings file,<br />
<tt class="docutils literal">settings.py</tt>, defines <tt class="docutils literal">MEDIA_ROOT</tt> and <tt class="docutils literal">MEDIA_URL</tt>, which are the<br />
path to the directory that hold the media and its URL on the server.<br />
We will serve site media from that URL.</li>
<li>Admin media, served by <tt class="docutils literal">MediaHandler</tt>: project settings file,<br />
<tt class="docutils literal">settings.py</tt>, defines <tt class="docutils literal">ADMIN_MEDIA_PREFIX</tt>, which is the URL prefix<br />
on the server. We will serve admin media from that URL.</li>
</ul>
<p>This is how <tt class="docutils literal">runcherrypy.py</tt> needs to be modified:</p>
<div class="highlight">
<pre><span class="o">...</span>
<span class="kn">import</span> <span class="nn">django.contrib.admin</span>

<span class="kn">from</span> <span class="nn">cherrypy.wsgiserver</span> <span class="kn">import</span> <span class="n">CherryPyWSGIServer</span><span class="p">,</span> <span class="n">WSGIPathInfoDispatcher</span>
<span class="kn">from</span> <span class="nn">devserver.mediahandler</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">os.path</span>
<span class="o">...</span>

    <span class="k">def</span> <span class="nf">handle</span><span class="p">(</span> <span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span> <span class="p">):</span>

        <span class="n">app</span> <span class="o">=</span> <span class="n">WSGIHandler</span><span class="p">()</span>

        <span class="n">path</span> <span class="o">=</span> <span class="p">{</span> <span class="s">'/'</span><span class="p">:</span> <span class="n">app</span><span class="p">,</span>
                 <span class="n">settings</span><span class="o">.</span><span class="n">MEDIA_URL</span><span class="p">:</span> <span class="n">MediaHandler</span><span class="p">(</span> <span class="n">settings</span><span class="o">.</span><span class="n">MEDIA_ROOT</span> <span class="p">),</span>
                 <span class="n">settings</span><span class="o">.</span><span class="n">ADMIN_MEDIA_PREFIX</span><span class="p">:</span>
                     <span class="n">MediaHandler</span><span class="p">(</span>
                         <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span> <span class="n">django</span><span class="o">.</span><span class="n">contrib</span><span class="o">.</span><span class="n">admin</span><span class="o">.</span><span class="n">__path__</span><span class="p">[</span><span class="mf">0</span><span class="p">],</span>
                                       <span class="s">'media'</span> <span class="p">)</span>
                         <span class="p">)</span>
               <span class="p">}</span>
        <span class="n">dispatcher</span> <span class="o">=</span> <span class="n">WSGIPathInfoDispatcher</span><span class="p">(</span> <span class="n">path</span> <span class="p">)</span>
        <span class="n">server</span> <span class="o">=</span> <span class="n">CherryPyWSGIServer</span><span class="p">(</span> <span class="p">(</span><span class="n">options</span><span class="p">[</span><span class="s">'host'</span><span class="p">],</span> <span class="n">options</span><span class="p">[</span><span class="s">'port'</span><span class="p">]),</span>
                                     <span class="n">dispatcher</span> <span class="p">)</span>
</pre>
</div>
<p>As you notice, we deduce the on-disk path of the admin media based on the<br />
<tt class="docutils literal">__path__</tt> variable of the imported <tt class="docutils literal">django.contrib.admin</tt> module.</p>
</div>
<div class="section" id="finally-a-test-application">
<h2>Finally, a test application</h2>
<p>First, a few practical thought on the layout of things. Django insists<br />
that <tt class="docutils literal">MEDIA_ROOT</tt> is an absolute path. If you are hosting your project<br />
completely with CherryPy, you will probably keep all your media files<br />
together with the project. I prefer to keep my media in a <tt class="docutils literal">media/</tt><br />
directory within my project directory. <tt class="docutils literal">settings.py</tt> features the<br />
following code to resolve <tt class="docutils literal">MEDIA_ROOT</tt> properly:</p>
<div class="highlight">
<pre><span class="n">MEDIA_ROOT</span> <span class="o">=</span> <span class="s">'media'</span>

<span class="kn">import</span> <span class="nn">os.path</span>
<span class="n">MEDIA_ROOT</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
               <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">normpath</span><span class="p">(</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">)</span> <span class="p">),</span>
               <span class="n">MEDIA_ROOT</span> <span class="p">)</span>
</pre>
</div>
<p>My applications start out from a simple structure:</p>
<pre class="literal-block">alpha/
 |-- __init__.py
 |-- models.py
 |-- views.py
 |-- urls.py
 |-- media/
 |    `-- ...
 `-- templates/
      `-- ...
</pre>
<p>This way, I can create symbolic links in the project <tt class="docutils literal">media/</tt><br />
directory like:</p>
<pre class="literal-block">$ ls -l media/
total 0
lrwxrwxrwx 1 arteme users 13 Feb 27 09:34 alpha -&gt; ../alpha/media/
</pre>
<p>which will make it easy to reference &#8220;alpha&#8221; application&#8217;s media in its<br />
template files as &#8220;<tt class="docutils literal"><span class="pre">{{MEDIA_URL}}alpha/...</span></tt>&#8220;</p>
<p>Attached is a simple test application that put all these things together.<br />
It features a project called <tt class="docutils literal">cherrytest</tt> with a single application app.<br />
The application has one view servers one HTML file with a 570&#215;562 image<br />
that is split into 35 100&#215;100 tiles. Happy hacking!</p>
<ul class="simple">
<li><a class="reference external" href="http://www.arteme.fi/wordpress/wp-content/uploads/2010/04/cherrytest.tgz">cherrytest.tgz</a></li>
</ul>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2009/02/26/django-cherrypy-dev-server-and-static-files/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Trac at site root with lighttpd 1.5.0</title>
		<link>http://www.arteme.fi/2007/08/20/trac-at-site-root-with-lighttpd-1-5-0/</link>
		<comments>http://www.arteme.fi/2007/08/20/trac-at-site-root-with-lighttpd-1-5-0/#comments</comments>
		<pubDate>Mon, 20 Aug 2007 13:37:19 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[trac]]></category>

		<guid isPermaLink="false">http://www.arteme.fi/?p=104</guid>
		<description><![CDATA[
For a long time I have been trying to set up trac to work as site root.
Consider a website http://trac.site.com/, I would like to have URL
http://trac.site.com/ point to default page (usually the wiki page
also served as http://trac.site.com/wiki), URL
http://trac.site.com/timeline point to the timeline page,
URL http://trac.site.com/roadmap point to the roadmap page, etc.
At no point should trac rewrite [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="trac-at-site-root-with-lighttpd-1-5-0">
<p>For a long time I have been trying to set up <a class="reference external" href="http://trac.edgewall.org">trac</a> to work as site root.<br />
Consider a website <tt class="docutils literal"><span class="pre">http://trac.site.com/</span></tt>, I would like to have URL<br />
<tt class="docutils literal"><span class="pre">http://trac.site.com/</span></tt> point to default page (usually the wiki page<br />
also served as <tt class="docutils literal"><span class="pre">http://trac.site.com/wiki</span></tt>), URL<br />
<tt class="docutils literal"><span class="pre">http://trac.site.com/timeline</span></tt> point to the timeline page,<br />
URL <tt class="docutils literal"><span class="pre">http://trac.site.com/roadmap</span></tt> point to the roadmap page, etc.<br />
At no point should trac rewrite the URLs to anything<br />
like <tt class="docutils literal"><span class="pre">http://trac.site.com/trac/timeline</span></tt>.</p>
<p>Such setup is possible with an <a class="reference external" href="http://www.apache.org">apache</a> webserver, but has been extremely<br />
difficult to get working with <a class="reference external" href="http://www.lighttpd.net/">lighttpd</a>. Fortunately, it is possible with<br />
lighty version 1.5.0. Here is the configuration of a working setup featuring<br />
<strong>lighttpd 1.5.0</strong> Subversion snapshot of revision 1900 and <strong>trac 0.10.4</strong>.</p>
<p>Since it is lighttpd version 1.5.0, we use the new <tt class="docutils literal">mod_proxy_core</tt> module<br />
to communicate with the trac FastCGI process spawned externally using<br />
the <tt class="docutils literal"><span class="pre">spawn-fcgi</span></tt> utility and listening for connections on localhost port<br />
9000.</p>
<p>The layout of <tt class="docutils literal">/var/www/trac.site.com/</tt> directory is as follows:</p>
<pre class="literal-block">/var/www/trac.site.com/
  |-- ...
  `-- htdocs
      |-- site-icon.ico
      |-- site-logo.png
      |-- ...
      `-- trac
      `-- ...
</pre>
<p>I want to serve static content from <tt class="docutils literal">/var/www/trac.site.com/htdocs</tt> and<br />
trac static content from <tt class="docutils literal">/var/www/trac.site.com/htdocs/trac</tt>. Static<br />
content includes website icon, website logo and whatever else I will manually<br />
upload in the future. Trac static content is the files provided by a trac<br />
installation and otherwise requested from <tt class="docutils literal"><span class="pre">.../chrome/common/</span></tt>.</p>
<p>This requires some modifications to the ini-file of the trac project.<br />
My <tt class="docutils literal">trac.ini</tt> has the following things set:</p>
<pre class="literal-block">[header_logo]
src = /htdocs/site-logo.png
...

[project]
icon = /htdocs/site-icon.ico

[trac]
htdocs_location = /htdocs/trac/
...
</pre>
<p>Note: if you don&#8217;t set <tt class="docutils literal">htdocs_location</tt> above, static trac content<br />
will be requested from <tt class="docutils literal">/chrome/common/</tt> directory instead. In this<br />
case, lighttpd will not handle the request itself, but will forward it<br />
to trac. This will not break anything, as trac will serve it&#8217;s static<br />
content without a glitch, but it may be slower in doing so than lighttpd.</p>
<p>The lighttpd configuration file looks like:</p>
<div class="highlight">
<pre>server.modules <span class="o">=</span> <span class="o">(</span> <span class="s2">"mod_alias"</span>,
                   <span class="s2">"mod_auth"</span>,
                   <span class="s2">"mod_proxy_code"</span>,
                   <span class="s2">"mod_proxy_backend_fastcgi"</span>,
                   ...
                 <span class="o">)</span>

...

<span class="nv">$HTTP</span><span class="o">[</span><span class="s2">"host"</span><span class="o">]</span> <span class="o">==</span> <span class="s2">"trac.site.com"</span> <span class="o">{</span>
  <span class="c"># trac-based website</span>

  <span class="c"># static content root</span>
  <span class="nb">alias</span>.url <span class="o">=</span> <span class="o">(</span> <span class="s2">"/htdocs/"</span> <span class="o">=</span>&gt; <span class="s2">"/var/www/trac.site.com/htdocs/"</span> <span class="o">)</span>

  <span class="c"># authentication settings</span>
  auth.backend <span class="o">=</span> <span class="s2">"htpasswd"</span>
  auth.backend.htpasswd.userfile <span class="o">=</span> <span class="s2">"/var/trac/trac.htpasswd"</span>

  <span class="nv">$HTTP</span><span class="o">[</span><span class="s2">"url"</span><span class="o">]</span> <span class="o">=</span>~ <span class="s2">"^/htdocs/"</span> <span class="o">{</span>
    <span class="c"># static concent</span>
  <span class="o">}</span>
  <span class="k">else</span> <span class="nv">$HTTP</span><span class="o">[</span><span class="s2">"url"</span><span class="o">]</span> <span class="o">=</span>~ <span class="s2">"^/login$"</span> <span class="o">{</span>
    <span class="c"># login handling</span>
    auth.require <span class="o">=</span> <span class="o">(</span> <span class="s2">"/"</span> <span class="o">=</span>&gt; <span class="o">(</span> <span class="s2">"method"</span>  <span class="o">=</span>&gt; <span class="s2">"basic"</span>,
                              <span class="s2">"realm"</span>   <span class="o">=</span>&gt; <span class="s2">"site.com trac website"</span>,
                              <span class="s2">"require"</span> <span class="o">=</span>&gt; <span class="s2">"valid-user"</span>
                            <span class="o">)</span>
                   <span class="o">)</span>
  <span class="o">}</span>

  <span class="nv">$HTTP</span><span class="o">[</span><span class="s2">"url"</span><span class="o">]</span> !~ <span class="s2">"^/htdocs"</span> <span class="o">{</span>
    <span class="c"># trac via fastcgi</span>
    proxy-core.protocol <span class="o">=</span> <span class="s2">"fastcgi"</span>
    proxy-core.backends <span class="o">=</span> <span class="o">(</span> <span class="s2">"127.0.0.1:9000"</span> <span class="o">)</span>
    proxy-core.rewrite-request <span class="o">=</span> <span class="o">(</span> <span class="s2">"_pathinfo"</span> <span class="o">=</span>&gt; <span class="o">(</span> <span class="s2">"^(/.*)"</span> <span class="o">=</span>&gt; <span class="s2">"$1"</span> <span class="o">)</span>,
                                   <span class="s2">"_scriptname"</span> <span class="o">=</span>&gt; <span class="o">(</span> <span class="s2">""</span> <span class="o">=</span>&gt; <span class="s2">"/"</span> <span class="o">)</span>
                                 <span class="o">)</span>
  <span class="o">}</span>
<span class="o">}</span>

...
</pre>
</div>
<p>The rewrite-request part doesn&#8217;t make sense, but it is the black magic<br />
that makes it actually work.</p>
<p>I&#8217;m sure there are better ways of achieving the same behavior. If you<br />
got the same result with lighttpd 1.5.0 with less hassle, I would like<br />
to hear from you.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2007/08/20/trac-at-site-root-with-lighttpd-1-5-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maemo SDK on Gentoo/AMD64</title>
		<link>http://www.arteme.fi/2007/04/29/maemo-sdk-on-gentoo-amd64/</link>
		<comments>http://www.arteme.fi/2007/04/29/maemo-sdk-on-gentoo-amd64/#comments</comments>
		<pubDate>Sun, 29 Apr 2007 13:20:05 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[amd64]]></category>
		<category><![CDATA[maemo]]></category>
		<category><![CDATA[xephyr]]></category>

		<guid isPermaLink="false">http://www.arteme.fi/?p=100</guid>
		<description><![CDATA[
Anyone who has tried installing Maemo SDK on a 64-bit system has run into
problems. Maemo SDK 2.2 and up (not that you would have more luck with
earlier versions) requires Scratchbox Apophis R4, which is 32-bit.
There are several pages on the web describing Maemo SDK installation on
Gentoo, 64-bit platform, or both:

http://plaes.org/blog/2007/02/15/maemo-sdk-on-gentoo/
http://danielkitta.org/howto/maemo-amd64

This is my story of how [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="maemo-sdk-on-gentoo-amd64">
<p>Anyone who has tried installing Maemo SDK on a 64-bit system has run into<br />
problems. Maemo SDK 2.2 and up (not that you would have more luck with<br />
earlier versions) requires Scratchbox Apophis R4, which is 32-bit.</p>
<p>There are several pages on the web describing Maemo SDK installation on<br />
Gentoo, 64-bit platform, or both:</p>
<ul class="simple">
<li><a class="reference external" href="http://plaes.org/blog/2007/02/15/maemo-sdk-on-gentoo/">http://plaes.org/blog/2007/02/15/maemo-sdk-on-gentoo/</a></li>
<li><a class="reference external" href="http://danielkitta.org/howto/maemo-amd64">http://danielkitta.org/howto/maemo-amd64</a></li>
</ul>
<p>This is my story of how I set up Maemo 3.1 SDK on Gentoo/AMD64&#8230;</p>
<p>First of all, you&#8217;ll need to download<br />
<a class="reference external" href="http://repository.maemo.org/stable/3.1/maemo-scratchbox-install_3.1.sh">http://repository.maemo.org/stable/3.1/maemo-scratchbox-install_3.1.sh</a> and<br />
<a class="reference external" href="http://repository.maemo.org/stable/3.1/maemo-sdk-install_3.1.sh">http://repository.maemo.org/stable/3.1/maemo-sdk-install_3.1.sh</a></p>
<div class="section" id="step-1-scratchbox">
<h2>Step 1: Scratchbox</h2>
<pre class="literal-block"># uname -a

Linux harmony 2.6.20-suspend2-r5-ae070426 #1 PREEMPT Thu Apr 26 12:03:31
EEST 2007 x86_64 AMD Turion(tm) 64 Mobile Technology MT-37 AuthenticAMD
GNU/Linux

# linux32
# uname -a

Linux harmony 2.6.20-suspend2-r5-ae070426 #1 PREEMPT Thu Apr 26 12:03:31
EEST 2007 i686 AMD Turion(tm) 64 Mobile Technology MT-37 AuthenticAMD
GNU/Linux

# bash ~/maemo-scratchbox-install_3.1.sh -s /maemo-3.1/scratchbox

...

# /maemo-3.1/scratchbox/sbin/sbox_adduser arteme yes

Scratchbox user account for user arteme added
</pre>
</div>
<div class="section" id="step-2-maemo-sdk">
<h2>Step 2: Maemo SDK</h2>
<p>After you have added yourself as a user to sbox group, you will need to<br />
start a new terminal, re-login, or whatever else you do to get the group<br />
membership updated. I simply do:</p>
<pre class="literal-block"># ssh 127.0.0.1
</pre>
<p>Then:</p>
<pre class="literal-block"># bash maemo-sdk-install_3.1.sh -s /maemo-3.1/scratchbox
</pre>
</div>
<div class="section" id="step-3-xephyr">
<h2>Step 3: Xephyr</h2>
<p>Xephyr is available in Gentoo as a kdrive USE-flag for xorg-server.<br />
Although if you want to run it natively in 64-bit mode, you&#8217;re out of luck!<br />
At the time of writing, there are a number of bugs that make X crash at<br />
startup or otherwise. In particular,<br />
<a class="reference external" href="https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/66996">https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/66996</a><br />
(or <a class="reference external" href="https://bugs.freedesktop.org/show_bug.cgi?id=8417">https://bugs.freedesktop.org/show_bug.cgi?id=8417</a> in freedesktop.org<br />
bugzilla) and others. Certain distributions have patched the bugs themselves<br />
(<a class="reference external" href="http://cvs.fedora.redhat.com/viewcvs/rpms/xorg-x11-server/devel/">http://cvs.fedora.redhat.com/viewcvs/rpms/xorg-x11-server/devel/</a>) and there<br />
are some fixes upstream<br />
(<a class="reference external" href="http://gitweb.freedesktop.org/?p=xorg%%2Fxserver.git&amp;a=search&amp;s=ephyr">http://gitweb.freedesktop.org/?p=xorg%%2Fxserver.git&amp;a=search&amp;s=ephyr</a>).<br />
However, for a painless installation I have used a 32-bit chroot environment.</p>
<div class="section" id="bit-chroot-environment">
<h3>32-bit chroot environment</h3>
<p>You can follow the <a class="reference external" href="http://www.gentoo.org/proj/en/base/amd64/howtos/index.xml?part=1&amp;chap=2">32-bit Chroot Guide</a> for Gentoo/AMD64 or use the<br />
<tt class="docutils literal"><span class="pre">x86-chroot</span></tt> package:</p>
<pre class="literal-block"># emerge x86-chroot
# rc-update add x86-chroot default
# /etc/init.d/x6-chroot start
</pre>
</div>
<div class="section" id="xephyr-in-32-bit-chroot-environment">
<h3>Xephyr in 32-bit chroot environment</h3>
<p>Enter the 32-chroot environment:</p>
<pre class="literal-block"># x86-chroot
</pre>
<p>Install Xephyr:</p>
<pre class="literal-block"># USE="kdrive -ipv6 -dri" VIDEO_CARDS="vga" emerge xorg-server
</pre>
<p><strong>You&#8217;re all set!</strong></p>
<p>Everything is installed, you&#8217;re all set! Don&#8217;t forget to start scratchbox on<br />
system start-up:</p>
<pre class="literal-block"># /maemo-3.1/scratchbox/sbin/sbox_ctl start
</pre>
<p>Start <tt class="docutils literal">Xephyr</tt>. You can do that through the <tt class="docutils literal"><span class="pre">x86-chroot</span></tt> as root, or<br />
better as a user:</p>
<pre class="literal-block">$ LD_LIBRARY_PATH=/opt/x86-chroot/lib:/opt/x86-chroot/usr/lib \
  /opt/x86-chroot/usr/bin/Xephyr :2 -host-cursor \
                                    -screen 800x480x16 -dpi 96 -ac
</pre>
<p>Log into scratchbox:</p>
<pre class="literal-block">$ /maemo-3.1/scratchbox/login

Welcome to Scratchbox, the cross-compilation toolkit!

Use 'sb-menu' to change your compilation target.
See /scratchbox/doc/ for documentation.

[sbox-SDK_X86: ~] &gt; export DISPLAY=:2
[sbox-SDK_X86: ~] &gt; af-sb-init.sh start
...
</pre>
</div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2007/04/29/maemo-sdk-on-gentoo-amd64/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subversion-only SSH users</title>
		<link>http://www.arteme.fi/2007/04/26/subversion-only-ssh-users/</link>
		<comments>http://www.arteme.fi/2007/04/26/subversion-only-ssh-users/#comments</comments>
		<pubDate>Thu, 26 Apr 2007 13:50:47 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[notes]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://g5.arteme.fi/wordpress/?p=63</guid>
		<description><![CDATA[
Sometimes you&#8217;re stuck with svn+ssh://&#8230; access for your repository. You need to give someone SSH access to access the repository, but you don&#8217;t want to give them full shell access. What you can do is create a group, whose users will only have access to svnserve.
Create a group called &#8220;svnonly&#8221;. /etc/groups will look something like:
...
svnonly:x:414
...

Then [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="subversion-only-ssh-users">
<p>Sometimes you&#8217;re stuck with <strong>svn+ssh://&#8230;</strong> access for your repository. You need to give someone SSH access to access the repository, but you don&#8217;t want to give them full shell access. What you can do is create a group, whose users will only have access to <em>svnserve</em>.</p>
<p>Create a group called &#8220;svnonly&#8221;. <em>/etc/groups</em> will look something like:</p>
<pre class="literal-block">...
svnonly:x:414
...
</pre>
<p>Then you can add users into that group. <em>/etc/passwd</em> will look something like:</p>
<pre class="literal-block">...
john:x:1001:414::/home/svnonly/john:/bin/bash
mike:x:1002:414::/home/svnonly/mike:/bin/bash
bob:x:1003:414::/home/svnonly/bob:/bin/bash
...
</pre>
<p>The home directory is entirely up to you &#8211; I choose <em>/home/svnonly</em> as a top directory for <em>svnonly</em>-users to keep them separate from full-access users and to keep <em>/home</em> neat. Yet, each can have their own home directory to have <em>.ssh/authorized_keys</em>, for example.</p>
<p>Next, add the following to your <em>/etc/ssh/sshd_config</em>:</p>
<pre class="literal-block">Match Group svnonly
        X11Forwarding no
        AllowTcpForwarding no
        ForceCommand svnserve -t
</pre>
<p>Now <em>svnonly</em>-users will have svnserve started for them automatically when they connect instead of a normal shell.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2007/04/26/subversion-only-ssh-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rendering an SVG to a GTK image</title>
		<link>http://www.arteme.fi/2007/03/26/rendering-an-svg-to-a-gtk-image/</link>
		<comments>http://www.arteme.fi/2007/03/26/rendering-an-svg-to-a-gtk-image/#comments</comments>
		<pubDate>Sun, 25 Mar 2007 22:00:49 +0000</pubDate>
		<dc:creator>arteme</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[svg]]></category>

		<guid isPermaLink="false">http://g5.arteme.fi/wordpress/?p=25</guid>
		<description><![CDATA[
Once upon a time loading SVG in python was done via pycairo and libsvg-cairo:

import cairo
import cairo.svg

svg = cairo.svg.Context()
svg.parse( 'filename.svg' )
...


Since then, libsvg-cairo has been deprecated (http://cairographics.org/PycairoFAQ). Nowadays, librsvg provides an SVG loader for GTK, so that it is possible to simply do

import gtk

i = gtk.Image()
i.set_from_file( 'x.svg' )
...


But I needed a finer control over the generation [...]]]></description>
			<content:encoded><![CDATA[<div class="document" id="rendering-an-svg-to-a-gtk-image">
<p>Once upon a time loading SVG in python was done via <tt class="docutils literal">pycairo</tt> and <tt class="docutils literal"><span class="pre">libsvg-cairo</span></tt>:</p>
<div class="highlight">
<pre><span class="kn">import</span> <span class="nn">cairo</span>
<span class="kn">import</span> <span class="nn">cairo.svg</span>

<span class="n">svg</span> <span class="o">=</span> <span class="n">cairo</span><span class="o">.</span><span class="n">svg</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
<span class="n">svg</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span> <span class="s">'filename.svg'</span> <span class="p">)</span>
<span class="o">...</span>
</pre>
</div>
<p>Since then, libsvg-cairo has been deprecated (<a class="reference external" href="http://cairographics.org/PycairoFAQ">http://cairographics.org/PycairoFAQ</a>). Nowadays, <tt class="docutils literal">librsvg</tt> provides an SVG loader for GTK, so that it is possible to simply do</p>
<div class="highlight">
<pre><span class="kn">import</span> <span class="nn">gtk</span>

<span class="n">i</span> <span class="o">=</span> <span class="n">gtk</span><span class="o">.</span><span class="n">Image</span><span class="p">()</span>
<span class="n">i</span><span class="o">.</span><span class="n">set_from_file</span><span class="p">(</span> <span class="s">'x.svg'</span> <span class="p">)</span>
<span class="o">...</span>
</pre>
</div>
<p>But I needed a finer control over the generation of image &#8211; in particular, I wanted to be able to zoom in to and out of the vector graphics image, much like <tt class="docutils literal"><span class="pre">rsvg-view</span></tt>. If you follow the example above and first render the image, then start scaling it, you will not get a high-resolution scaled vector image, but a scaled low-resolution rendering of the vector image.</p>
<p>After reading the <tt class="docutils literal"><span class="pre">rsvg-view</span></tt> sources, I figured out that what I wanted could be accomplished by:</p>
<ol class="arabic simple">
<li>Request an SVG loader from GTK/GDK</li>
<li>Set the desired image size</li>
<li>Load the image</li>
<li>Set the image to the resulting pixbuf</li>
</ol>
<p>The following code does the magic:</p>
<div class="highlight">
<pre><span class="c"># svg_data - a string containing the contents of the SVG file</span>
<span class="c"># image - an instance of gtk.Image</span>
<span class="c"># w, h - desired image resolution</span>

<span class="n">loader</span> <span class="o">=</span> <span class="n">gtk</span><span class="o">.</span><span class="n">gdk</span><span class="o">.</span><span class="n">PixbufLoader</span><span class="p">(</span> <span class="s">'svg'</span> <span class="p">)</span>
<span class="n">loader</span><span class="o">.</span><span class="n">set_size</span><span class="p">(</span> <span class="n">w</span><span class="p">,</span> <span class="n">h</span> <span class="p">)</span>

<span class="n">loader</span><span class="o">.</span><span class="n">write</span><span class="p">(</span> <span class="n">svg_data</span> <span class="p">)</span>
<span class="n">loader</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

<span class="n">pb</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">get_pixbuf</span><span class="p">()</span>
<span class="n">image</span><span class="o">.</span><span class="n">set_from_pixbuf</span><span class="p">(</span> <span class="n">pb</span> <span class="p">)</span>
</pre>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.arteme.fi/2007/03/26/rendering-an-svg-to-a-gtk-image/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
