Naughty Hits

Recently I started keeping track of "people" (trojaned Windows boxes) looking for things like formail.cgi or mt-comments.cgi on my work webserver. Having now hit the 1000 unique IP address mark I thought I'd graph the locations of the offenders with geoip.

The full graph shows the USA on top by a large margin, but Spain not far behind with UK, Italy and France rounding out the top 5.

What does this mean? Nothing, really; except with a bit of coercion Openoffice can be made to make quite a nice graph (tip: to just export the graph copy it into a new "Drawing" then export that to PDF).

on threads under linux

Other questions that come up about threads

How many threads can I run? This depends on a number of things

  • The ulimit of the user. Set the number of threads with ulimit -u (or somewhere like /etc/security/limits.conf).

  • The default stack size. By default, the stack size of a new thread is quite large, in the region of megabytes. It's not going to take you long to run out of memory for new stacks. Luckily, pthread_attr_setstacksize() allows you use smaller stacks.

  • The kernel. The kernel won't allow you to fill up your entire memory with thread descriptors. See kernel/fork.c:fork_init()

    /*
      * The default maximum number of threads is set to a safe
      * value: the thread structures can take up at most half
      * of memory.
      */
      max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);
    

    I belive this works out to around 4000 threads on a 256Mb x86 machine; YMMV of course.

What does ps show me? By default, ps should only show you the parent thread. Try with -m for the child threads.

checking for NPTL

This question seems to come up constantly. A compile time check for NPTL probably isn't what you want, since you can easily turn NPTL on or off on a program with something like LD_ASSUME_KERNEL. The following snippet is, AFAIK, the best way to check for NPTL support.

#include <stdio.h>
#include <unistd.h>
#include <alloca.h>
#include <string.h>

int isnptl (void)
{
    size_t n = confstr (_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
    if (n > 0)
    {
        char *buf = alloca (n);
        confstr (_CS_GNU_LIBPTHREAD_VERSION, buf, n);
        if (strstr (buf, "NPTL"))
            return 1;
    }
    return 0;
}

int main(void)
{
    printf("NPTL: %s\n", isnptl() ? "yes" : "no");
    return 0;
}

But more important is why are you checking?.

inkscape

Last night I tried to use inkscape to do some graphic design type work. Here's my (point format) review from start to finish

  • It's not 64 bit clean. It doesn't even start on an IA64 box, and it's something to do with glib and quarks and string lists which will take more time to track down than I have, unfortunately. The code is huge; the build directory ended up hitting the 600mb mark. The best I can do at this stage is offer one of the developers a login.
  • Once working on my ibook, I was pleasantly surprised with everything but the colour chooser. There is no eye-dropper tool that I could find, and no way to store a palette of colours either, so I was forced to remembering and typing in RGB colours. If you copy and object and then edit it's colour properties, it defaults back to black. The gradient tool is fairly non-intuitive, giving strange names to stops. This was frustrating. Everything else, however, worked great.
  • The inbuilt bitmap tracing tool was really nice.
  • I was quite impressed with the final output. It looked great on the screen.
  • I needed a PDF. So I exported to to postscript, and it just looked wrong. For a start, the alpha transparency doesn't export to postscript at all, so things that were looking grey on the screen were just black. On one piece of clipart, the export had dropped a few bits leaving white gaps in the picture. It seemed to have rasterised some of the output, especially the stuff I bitmap traced, making it look really dodgey.
  • I imported the SVG into Illustrator, hoping it would save better PDF's. Illustrator also ignored the alpha transparency, but, more worryingly, when constraining the artboard to a particular size in Illustrator the Inkscape output seemed to be about 4cm larger than the (supposedly same) artboard size. I don't know who is right, but I trust Illustrator. I can't be sending wrong sized artwork to a printer, because they will just crop the overflow.

All said, trying to use Inkscape to quickly get artwork into PDF format for printing hasn't really worked all that well for me. I've had to use Illustrator to tweak the final output. With a few UI enhancements (which are happening in current dev versions) and a first-class export to PDF it would put a strong link in the linux-as-a-desktop chain.

reading rdtsc on amd64

On an 386 you can read the rdtsc by simply doing

unsigned long long result;
__asm__ __volatile__("rdtsc" : "=A" (result));

Note, however, in the gcc docs the documentation for the =A constraint has an important caveat

Specifies the a or d registers. This is primarily useful for 64-bit integer values (when in 32-bit mode) intended to be returned with the d register holding the most significant bits and the a register holding the least significant bits.

Thus this is not what you want when using amd64 in 64 bit mode with 64 bit registers. Follow the example of the kernel code, and do the shifts by hand

#define rdtscll(val) do { \
     unsigned int __a,__d; \
     asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
     (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
} while(0)

footnote: why oh why can't everyone use a real 64 bit architecture?

xchat notifier plugin

I previously mentioned that there must be a better way to make xchat pop up a dialog box, and of course there is, the plugin!

It's so easy; though finding the text command to match is a bit obscure. Here it is

__module_name__ = "gnome-notifier-plugin"
__module_version__ = "1.0"
__module_description__ = "notify of channel events via gnome-notify"

import xchat
import os

def channel_message(word, word_eol, userdata):

    err = os.system("/usr/bin/gnome-notify " +
                    "\'<font color=\"red\">New channel message</font></br>" +
                    "<b>"+word[0]+"</b><br>"+word[1]+"\'")
    if (err != 0):
        print("Failed to launch gnome-notify!")
    return xchat.EAT_NONE

xchat.hook_print("Channel Msg Hilight", channel_message)

you just put that in your .xchat2 directory and next thing you know you should have screenshots like that below!

gnome-notifier xchat plugin

.Xresources

the .Xresources file is in the format classname*paramater: value. Once you change it, you need to either log out or run xrdb -merge ~/.Xresources.

You should be able to set .Xdefaults to do much the same thing without reloading.

To find the class name, use the xprop utility to look for WM_CLASS, e.g. for xtightvncviewer

ianw@mingus:~$ xprop WM_CLASS
[click on xtightvncviewer window]
WM_CLASS(STRING) = "xtightvncviewer", "Vncviewer"
ianw@mingus:~$ cat ~/.Xresources
xtightvncviewer*grabKeyboard: True

Most applications use a client name that is the executable name with a capital letter, but xtightvncviewer doesn't quite follow this rule.

undefined functions

So I found a bug (it's probably shouldn't really be "important" but I do include a fix). I know why this bug happens, undefined functions are assumed to return an int, so it chops off the top of a 64 bit pointer.

but why? delving into the standards is tricky. first some terms

  • a function declaration gives the function name and the paramaters. It has a return type, a name and a paramater list. Each of the paramaters is possibly named (C99 6.7.5.3.6 : ...specifies the types of, and may declare identifiers for, the parameters of the function and later, C99 6.9.1 : If the declarator includes a parameter type list, the declaration of each parameter shall include an identifier). It looks like

    int afunction(int aparamater)
    

    .

  • a function prototype is like a weak version of a function declaration. It specifies the return value and the paramaters, but doesn't give the paramater names (C99 6.2.1 : A function prototype is a declaration of a function that declares the types of its parameters). This is used for C++ compatability, I think. It looks like

    int afunction(int)
    

    So you can say a function prototype is always a function declaration, but a function declaration isn't always a prototype.

  • a function definition is where you actually write the function. It looks like

    int afunction(int aparamater) { return aparamater; }
    

    Note that a function definition is also a declaration, which is why you can happily use functions after they are defined in the source code.

Ian Lance Taylor suggested the relevant part of the C99 standard dealing with undefined functions says

6.5.2.2; Paragraph 1 : The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.

The disallows undefined functions by omission; they're not mentioned so they're not allowed. Actually, a little earlier when defining exactly what an expression is (6.5.1.2) we get one definition of a primary expression

An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator)76 76: thus, an undeclared identifier is a violation of the syntax.

An undeclared identifier is not considered a primary expression. What's an expression? Think of it as anything that can go to the right hand side of an = or as the conditional of an if( ) statement.

So, a function declaration is just another type of declarator (C99 6.5.7) which declares an identifier which is the function name (e.g. in the same way int i declares i as being an identifier of integer type, int function(void) declares function() as an identifier of a function that returns int taking no arguments).

Ian Lance Taylor goes on to say

Given traditional C usage, requiring a function declaration can be reasonably viewed as a pedantic requirement, appropriate for -pedantic-errors. In general, if you want gcc to enforce strict adherence to the relevant standard, you must use -pedantic-errors. Of course there is a very reasonable coding style in which functions should always be declared for use. For that coding style, there is -Werror-implicit-function-declaration.

The only problem with this is that no one ever actually turns on those flags, and on 32 bit system (which most of the world use) it doesn't cause an error because the pointer is the same size as an int.