*this
home about contact feed
projects
vagra vaBlo
categories
C++(7) Solaris(4) tntnet(3) vi(3) Linux(2) DeleGate(2) Postgres(2) proxy(2) cxxtools(1) regex(1) readline(1) dtrace(1) gcc(1) MeeGo(1) ssh(1) firefox(1)

Changing users shell on MeeGo

MeeGo uses busybox as default shell for root as well as for the unprivileged default user. This might be unpleasant for some people escpecially since it doesn't support the vi-mode. Installing an other shell is easy, however if you want to switch the default shell you need to be carefull.

Since some scripts will get executed by the users shell early at boot, changing the shell of root or the user might leave your system unbootable. You system will also stop booting if you load a shell via the users .profile without checking, so here is how you can load it via .profile:

MYSHELL=~/bin/mksh

if [ ${TERM} != "linux" ] && [ ${SHELL} == "/bin/sh" ] && [ -x ${MYSHELL} ]; then
        SHELL=${MYSHELL}
        export SHELL
        exec ${MYSHELL}
fi

Of course MYSHELL can be any shell installed on the system. The important part is the check if TERM is "linux", since all scripts executed by the os will have that TERM, while remote ssh sessions or terminal emulators will typically have "xterm" setted.

While this is expected also to work on maemo or Sailfish OS, i did tested it on Harmattan only. Thus you might check first, by temporary adding "env >> /tmp/user.env" to the .profile and reboot.

libcxx on linux

Currently Clang is shipped using GNUs STL by default, which is basically a C++98 library with some C++11 features added. libc++ is LLVMs C++11 implementation of the C++ Standard Library, which is written for C++11 and thus might provide some benefits for C++11 code. Also there are some license concerns with GNUs STL, however, as of today, you don't really get rid of GNU dependencies it if you use Clang on linux.

While Clang support for libc++ and the library itself is envoling, you still need to compile libc++ and libc++abi on your own. At least i don't know about any distributions which package Clang with libc++ included.

libc++

Installing libc++ is easy. For this article, i ignore packaging as well as any distro-specific concerns, you should easily be able to adjust the steps to your distribution. You need to install Clang first and need to know where Clangs prefix is, i assume /usr

export BASEDIR="$PWD"
svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx
cd libcxx/lib
./buildit
sudo cp libc++.so.1.0 /usr/lib/
sudo cp -R ../include /usr/include/c++/v1
sudo ln -s libc++.so.1.0 /usr/lib/libc++.so
sudo ldconfig

libc++abi

libc++abi apperas to be not very well tested on linux, the primary developmentplatform is Mac OS-X. To compile it, you'll need to copy gccs internal unwind.h, that will be found in the libdir of gcc. Also i needed to replace __unwind_word__ with __word__, which might or might not be identically on your platform

cd $BASEDIR
svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi
cd libcxxabi/include
sed 's/__unwind_word__/__word__/g' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.1/include/unwind.h > unwind.h
cd ../lib
./buildit
sudo cp libcxxabi/lib/libc++abi.so.1.0 /usr/lib
sudo ln -s libc++abi.so.1.0 /usr/lib/libc++abi.so
sudo ldconfig

Testing

Now you can use libc++ it if you add the right paramenters to clang++

clang++ -std=c++11 -stdlib=libc++ -lc++abi -o test test.cpp

Unfortunately the implementation is still incomplete. However, it might be complete enough for you to play arround with some features. If you run the test, you'll see what is working.

cd $BASEDIR/libcxx/test
export OPTIONS="-std=c++11 -stdlib=libc++ -lc++abi"
./testit

Most tests are passing allready, however, there are some important features that are not working and of course, there is no evidence, that the tests cover the full featureset of C++11.

Results for libcxx/test:
using clang version 3.1 (branches/release_31)
Target: x86_64-unknown-linux-gnu
Thread model: posix
with -std=c++11 -stdlib=libc++ -lc++abi  
----------------------------------------------------
sections without tests   : 0
sections with failures   : 51
sections without failures: 1013
                       +   ----
total number of sections : 1064
----------------------------------------------------
number of tests failed   : 186
number of tests passed   : 4153
                       +   ----
total number of tests    : 4339
****************************************************

integral operators and int

Consider you have a class that contains operator bool() and for example operator unsiged(). What will happen if you try to convert it to let's say short?

#include<iostream>

int main(void)
{
        class Foo
        {
            public:
                operator bool() { return 1; }
                operator unsigned() { return 2; }
        } foo;

        std::cout << "Result: " << (short) foo << std::endl;

        return 0;
}

You will get an error about an ambiguous conversion. But if you convert it to int, the game will be changed, it compiles and runs:

$ CC -o foo foo.cpp && ./foo 
Result: 1

It picks operator bool(), which might surprise in the first place, but makes perfectly sense, since it is sure, that there will be no dataloss during the conversion from bool to int. But shouldn't this also be true for short? It surely is, however the C++ standard[1] is very clear about it, only a conversion from bool to int is allowed due integral promotion. The same is true, if you have operator short() and operator unsiged(), as long as only one of the operators result can be lossless converted to int, it will be picked. The special treatment in the standard for the type int is somewhat inconsistent, however, we have to live with it and at least on all compilers i tested, i got the same behavior. So it's safe to assume that you need only to keep int in mind if you use multiple operators with integral return values.

If you want to make sure, that an conversion to int uses operator unsiged(), just add an operator int() that casts from unsigned. This will also work in polymorphic classes so you add an operator int() to the baseclass that will call operator unsigned() of the derived class.

#include<iostream>
int main(void)
{

        class Foo
        {
            public:
                operator bool() { return 1; }
                virtual operator unsigned() { return 2; }
                operator int() { return (unsigned) *this; }
        };

        class Bar: public Foo
        {
            public:
                operator unsigned() { return 3; }
        } bar;

        std::cout << "Result: " << (int) bar << std::endl;

        return 0;
}
$ CC -o foo foo.cpp && ./foo 
Result: 3

[1] ISO/IEC 14882:1998 -- 4.5 - Integral promotions [conv.prom]

http proxy with ssh

If you work on a remote host which is behind a firwall that doesn't allow outgoing HTTP, installing software can become cumbersome, especially for tools like Rubys gem or Perls CPAN. Fortunately, the most tools support using a proxy configuration from environment variables and you can tunnel almost everything thru SSH.

If you can reach a remote host via ssh, you can use ssh -D, however, that does work only one way. Of course, you'll come up with a solution to reverse the order by einther forwarding port 22 or make your socks proxy using ssh -D port localhost. This however solves the problem only partially, since there is no widely available support for taking a socks proxy from the environment and you don't want to mess with teaching all the package managers what command line arguments they need to pass.

A much easier solution is to use delegate as proxy. You just run a local http proxy and forward it's port via SSH:

local$ delegated -P127.0.0.1:8080 SERVER=http
local$ ssh -R8080:127.0.0.1:8080 user@remote
remote$ http_proxy=http://127.0.0.1:8080
remote$ export http_proxy

And you're done, you can test with curl or wget, but CPAN and gem install will also work.

remote$ curl http://www.example.com/

cookie check in tntnet

Tntnet uses session cookies for keeping track of the client if there are variables defined in the <%session> scope. However, if you rely on clients accepting and sending cookies, you application might work erronous.

For example you could redirect the client to a login page, if there is no valid session set. If the client does not accept cookies, it would end in a redirection loop until the client detects the loop, stops sending requests and displays an inconvenient error page.

To fix that, you could enable some JavaScript to test if the client has cookies enabled, however this would not work for these clients, who doesn't have JavaScript enabled and also would most likely ignore exceptions the user might want to set just for you.

A better way is to check the cookie support with a redirect, here is an example for tntnet:

<%session scope="global">
  bool cookies = false;
  bool redirected = false;
  std::string orig_query;
</%session>
<%cpp>
  if(!cookies) 
  {
    if(request.getQueryString() == "cookietest")
      reply.redirect("/error/nocookie");
    orig_query = request.getQuery();
    cookies = true;
    reply.redirect("/login?cookietest");
  }
  if (!redirected)
  {
    redirected = true;
    reply.redirect(orig_query);
  }
</%cpp>

First it checks if the cookie variable is set to false, if so it checks if the URL parameter is "cookietest" which the test would set later. If cookietest is the url parameter, it's safe to assume, that the browser has been redirected before and therefore will redirect the client to "/error/nocookie" which can deliver an appropriate error message

If the cookie variable is false and the url parameter is not "cookietest", it will store the original request in orig_query, set cookie to true and redirects to the testpage.

If the cookie variable is true, cookies are enabled and it's save to redirect to the original Page. To prevent a redirection loop when the original url will for what ever reasons cause the test again, we also set redirected to true

pentadactyl

I used Vimperator to have a vi like userinterface in firefox for many years and it was great. However, the latests developments in Vimperator i didn't like much.

Fortunately, some of the developers seem the agree with my understanding of a pleasant user experience and created Pentadactyl which feels just like Vimperator 2, but also with Firefox 7. Here's my .pentadactylrc

set autocomplete=0
set guioptions=Ccs
set showtabline=never
set noerrorbells

ecpp include

ecpp is the template language used in tntnet to join C++ with HTML. If you want to split your application into multiple ecpp files, you have two possibilities. You can either make it a subcomponent that you call using <& subcomponent>, or you can include the ecpp code using <%include>. Most people seem to prefere calling subcomponents, so if i prefere the other way, i should have good reasons.

If you create a subcomponent, you get an independent component that get called as a function. You can pass arguments to the component, but you don't have access to the scope of the calling component. The argument types are very limited you can only pass strings, or types that can be converted to strings. If your subcomponent takes arguments other than strings, ecpp will use tnt::stringTo<type> to convert the argument from a string to your type. The argument will always be a copy of a string, you can't pass by reference or a pointer to a string.

subcomponent example

So, if you want to use a subcomponent to printout parts from you own types, you need to pass the strings to the subcomponent. as example lets take a vector<string> and fill it with 100 strings. For printing we use a subcomponent called in a loop.

<html>
 <head>
  <title>include test</title>
 </head>
 <body>
<h1>main</h1>
  <{
        std::vector<std::string> vec;
        for(int i=0; i<100; i++)
        {
                std::ostringstream s;
                s << "string" << i;
                vec.push_back(s.str());
        }
   }>
  <h2>print a vector of 100 strings</h2>
% for(std::vector<std::string>::const_iterator it = vec.begin(); it < vec.end(); it++) {
    <& comp arg1=*it >
% }
 </body>
</html>

The subcomponent comp takes one string as argument, it is very simple.

<%args>
        arg1;
</%args>

<p>argument: <$ arg1 $></p>

include example

The include example is very similar, but instead of calling a function to printout the string, the included ecpp becomes the body of the for loop. That saves a function call for each iteration of the loop, but more important, we don't need to copy the string to a different component.

<html>
 <head>
  <title>include test</title>
 </head>
 <body>
<h1>main</h1>
  <{
        std::vector<std::string> vec;
        for(int i=0; i<100; i++)
        {
                std::ostringstream s;
                s << "string" << i;
                vec.push_back(s.str());
        }
   }>
  <h2>print a vector of 100 strings</h2>
% for(std::vector<std::string>::const_iterator it = vec.begin(); it < vec.end(); it++) {
<%include>
  incl.ecpp 
</%include>
% }
 </body>
</html>

The included file is even more simple. Notice, that it prints out whatever it points to, there is no defenition what type it is, so it really depends on what file includes it. This way it is possible to use the same include file for may different ecpp components with differnet types, as long as the objects in the components have the same name used in the include file and have all required operators and members.

<p>outstr: <$ *it $></p>

Comparing

When talking about performance we should first consider if it does matter. To find out how large the overhead of the subcomponent variant is, i used siege to compare both components, the first, mapped to /comp, uses the subcomponent printout, the second uses include.

$ ./siege -c 100 -b -r 1000 'http://127.0.0.1:8000/comp'
** SIEGE 2.70
** Preparing 100 concurrent users for battle.
The server is now under siege..      done.
Transactions:                 100000 hits
Availability:                 100.00 %
Elapsed time:                 260.25 secs
Data transferred:              35.95 MB
Response time:                  0.25 secs
Transaction rate:             384.25 trans/sec
Throughput:                     0.14 MB/sec
Concurrency:                   97.20
Successful transactions:      100000
Failed transactions:               0
Longest transaction:           24.58
Shortest transaction:           0.00
$ ./siege -c 100 -b -r 1000 'http://127.0.0.1:8000/incl'
** SIEGE 2.70
** Preparing 100 concurrent users for battle.
The server is now under siege..      done.
Transactions:                 100000 hits
Availability:                 100.00 %
Elapsed time:                 112.77 secs
Data transferred:              33.95 MB
Response time:                  0.11 secs
Transaction rate:             886.76 trans/sec
Throughput:                     0.30 MB/sec
Concurrency:                   94.05
Successful transactions:      100000
Failed transactions:               0
Longest transaction:           13.64
Shortest transaction:           0.00

So the difference is quite large, i got more than twice as much requests/sec done when using the include variant. Of course the example application is very simple, but i do use small ecpp snippets all the time to print a few strings from my objects. If you for example what to share the HTML headers for all sites but want to change <title>, it would become much faster, if you use include instead of passing the title string to a subcomponent.

Also i take advantage of the fact that include is type agnostic, if i just like to call object.getText() with some surrounding HTML, it really doesn't matter, what type the object is, as long as it have a member funktion getText() that returns something that can be converted to a string.

Subcomponents also have it's application, if you have larger subroutines that acts independent from the calling component and is called by multiple components, a subcomponent is typically to prefere. The overhead of calling a subcomponent especially without parameters is not that large and you can benefit from a smaller binary size, since a subcomponent get only included once in the whole application.

readline vi-mode

If you like to use your shell in vi mode, it's very likely you also love to have a vi-mode in psql and mysql or just everywhere. This is achievable if the tool of your choice can be compiled with readline support. Just check ldd if it is the case:

$ ldd `which psql` | grep readline
        libreadline.so.6 => /lib64/libreadline.so.6 (0x0000003ad1000000)

If so, you can enjoy using vi-mode in psql by enabling the readline vi-mode:

echo 'set editing-mode vi' >> ~/.inputrc

This enables vi-mode for all commandline tools linked against readline. Interestingly it also enables a more advanced tab completion in mysql. DESCR<tab> will now expand to DESCRIBE for example.

Singleton template instantiation

When you create a sigleton, you want to have exact one instance in your programm. But what does happen if you have a singleton template that get instantiated multiple times. I did a simplified test to show what happens.

DeleGate

DeleGate is just amazing, it is not only a very simple HTTP and SOCKS proxy, it also can redirect TCP Ports to a host in an other network or provide the content of a /etc/hosts file as DNS Server and much more. Here are a fews usage examples.

Simple HTTP reverse Proxy, caching behaviour can be controlled optionally

delegated -P80 SERVER=http://www.vtoc.de/

Forwarding a TCP (Postgres in this case) Port. This can be usefull, if you migrate the database to an remote host and you canot take the ip with you. An IP after -P tells delegate to bind that address only

delegated -P10.20.20.42:5432 SERVER=tcprelay://172.16.20.23:5432/

Tunnel a TCP connection thru a socks proxy

delegated -P10.20.20.42:5432 SERVER=tcprelay://172.16.20.23:5432/ SOCKS=proxyhost:port

Making an HTTPS only service available to HTTP clients

delegated -P80 SERVER=http MOUNT="/* https://httpshost/*" STLS=fsv:https

SSL proxy for ftp

delegated -P990 SERVER=ftps MOUNT="/* ftp://localhost/*" STLS=fsv

Standalone HTTP Server

delegated -P80 SERVER=http MOUNT="/* file:/var/www/html/*"

DNS Server from hosts file

delegated -P53 SERVER=dns RESOLV=file:/etc/hosts

DeleGate can do much more, like cronjobs or run as inetd server, best you look into the documentation.

1 2 ยป Next