Leap year bug crashes Zune

Microsoft’s 30GB Zune players fail to work today (Dec 31).

The problem has been identified - A bug in the freescale firmware leads to an infinite loop on the last day of a leap year.
year = ORIGINYEAR; /* = 1980 */

while (days > 365)
   if (IsLeapYear(year))
      if (days > 366)
         days -= 366;
         year += 1;
      days -= 365;
      year += 1;

If such poor codes were found in an airplane, or a medical device, ooops, it should be terrible..

Migrating to EXT4

Ext4, the successor to ext3 which was formerly known as ext4dev, is marked stable in Linux kernel 2.6.28, meaning the Linux kernel team now recommends using ext4 in production.

To convert a file system from ext3 to ext4, use
tune2fs -O extents /dev/DEV
and remount the file system as ext4. (Two e2fsck runs are recommended before and after tune2fs.) Some documentations also include the -E test_fs option. This is not necessary now since ext4 is no longer experimental.

Finally do not forget to modify /etc/fstab.

An ext4 file system created this way is not a “true” ext4 - the extents feature, the main advantage of ext4 comapred to ext3, is not automatically applied to old files. New files created afterwards are in the extents format.

Unlike the 100% backward compatibility of ext3 with ext2, an ext4 file system can no longer be mounted as if it were an ext3, unless the extents feature is disabled. (If you want to disable extents, why not simply use ext3?)

cross distcc

It is possible to distribute compilations to machines with different architectures.

Here is an example, to allow distributing tasks from a 64-bit system (x86_64) to 32-bit systems (i686):

First of all, both the client and servers should have distcc installed, of course. Then run the distcc daemon at the servers. Be careful so that they are not refusing connections from the client.

The distcc servers should also have the corresponding cross toolchains installed.
In Gentoo, this is simple. Emerge crossdev and run crossdev --target x86_64-pc-linux-gnu. (Experience tells us it is better to stip -march=... from CFLAGS when building the cross toolchain, otherwise we may (or may not) encounter strange errors, though some options like -march=nocona are valid on both i686 and x86_64. The reason is beyond me...)

Then commands x86_64-pc-linux-gnu-{gcc,g++} should be available.

Most source packages are created with autotools, so they honor the environment variables CC and CXX. At the client end, export CC='distcc x86_64-pc-linux-gnu-gcc' and CXX='distcc x86_64-pc-linux-gnu-g++' before compiling.

It is important to use the full compiler name including the host architecutre (x86_64-pc-linux-gnu in this example). Otherwise the distcc servers call the native compilers, resulting in incompatible object files.

Alternatively you may want to use the “transparent” method of calling distcc: PATH="/usr/lib/distcc/bin:$PATH" make. This does not work automatically. Instead, it is necessary to use a wrapper script to make sure the architecture is explicitly specified:
# cd /usr/lib/distcc/bin
# rm cc c++ gcc g++
# echo '#!/bin/bash' > distcc-wrapper
# echo 'exec /usr/lib/distcc/bin/x86_64-pc-linux-gnu-g${0:$[-2]} "$@"' >> distcc-wrapper
# chmod +x distcc-wrapper
# ln -s distcc-wrapper cc
# ln -s distcc-wrapper c++
# ln -s distcc-wrapper gcc
# ln -s distcc-wrapper g++

[1] DistCC Cross-compiling Guide - Gentoo Documentation

How BASH Changes Terminal Window Title

In many distributions bash automatically changes the terminal title. I thought it was hardcoded in bash, but it turns out to be not. It is usually implemented with PROMPT_COMMAND.

Environment variable $PROMPT_COMMAND defines the command to be automatically executed before displaying the primary prompt (i.e. $PS1). It is set by a script that is sourced by interative instances of bash. In Gentoo it is in /etc/bash/bashrc:
case ${TERM} in
        PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\007"'
        PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/$HOME/~}\033\\"'

In fact, the first version above also works with newer versions of screen.

MATLAB matrices are in column-major storage

Authors of each and every high-level programming language claim you only have to care the semantics of its statements without worrying about its internal implementation. Unfortunately, this can hardly be true.

Today I was working on some MATLAB codes. One of them scales each row of a sparse matrix to make its 1-norm equal to 1. The matrix I worked on was 20000×20000, with 153306 nonzero entries.

This is the first version:
for k = 1:N
 s = sum(P(k,:));
 if s ~= 0
  P(k,:) = P(k,:)/s;
This did not stop in 20 seconds, until I pressed Control-C.

This is the second version:
P = P';
for k = 1:N
 s = sum(P(:,k));
 if s ~= 0
  P(:,k) = P(:,k)/s;
P = P';
This finished within one second.

[All entries of matrix P are known to be positive, so I simply use sum to get the 1-norm of a row/column.]

The reason is simple. MATLAB internally stores sparse matrices in compressed column format[1]. Therefore, it is many times more expensive to extract or insert a row than column.

ps. For dense matrices, MATLAB also uses column-major formats, following the FORTRAN convention, though MATLAB is itself written in C (and the GUI in Java) [1].


[1] J. Gilbert, C. Moler and R. Schreiber. Sparse matrices in MATLAB: Design and implementation. SIAM Journal on Matrix Analysis, 1992.

GCC #pragma pack bug

#pragma pack is accepted by many C/C++ compilers as the de facto standard grammar to handle alignment of variables.

However there is an old bug in GCC, reported many times, the first of which was in 2002, still not fixed now.
#include <cstdio>
using namespace std;

#pragma pack(1)
template <typename T>
struct A {
    char a;
    int b;
A<int> x;
#pragma pack(2)
A<char> y;
#pragma pack(4)
A<short> z;

int main()
    printf ("%d %d %d\n", sizeof x,sizeof y,sizeof z);
    return 0;

This gives 5 6 8 instead of 5 5 5 as we may expect. (VC++ and ICC both give the more reasonable 5 5 5.)

This example is not very bad. Even worse is, that this bug can damage programs that use STL. Here is an example:

#include <cstdio>
#include <map>
using namespace std;

#pragma pack(1)
void foo (const map<short,const char*> &x)
    for (map<short,const char*>::const_iterator it=x.begin();
            it!=x.end(); ++it)
        printf ("%d %s\n", it->first, it->second);

#include <map>
using namespace std;

void foo (const map<short,const char *> &);

int main()
    map<short, const char *> x;
    x[0] = "Hello";
    x[1] = "World";
    foo (x);

Compile a.cpp and b.cpp separately and link them together. This program segfaults if compiled with GCC, but works well with ICC or VC++.

In conclusion, for better portability and/or reliability, never use #pragma pack unless absolutely necessary. If really unavoidable, always push and pop immediately before and after the structure definition. (If the program is intended to be compiled by GCC/ICC only, it is better to use the more reliable GCC-specific __attribute__((__packed__)).)

PS. It seems Sun CC (shipped with Solaris) also has this bug. It fails for the first example here, but for the second it works well. I don't know how manages to align pair<short,const char *> correctly...

su without password

Google returns a lot of meaningful results for “sudo without password” and “ssh without password.” I don’t know why googling “su without password” gives no useful info.

To allow a user to become root with su without entering the password, edit /etc/pam.d/su.

For example, in Gentoo (should be the same or similar in other distros) uncommenting the following line allows users in group wheel to su without password:
auth sufficient pam_wheel.so use_uid trust

Send Ctrl-A to sessions in SCREEN

C-A servers as the command hotkey in SCREEN. To send Ctrl-A to the session in SCREEN, simply use C-A a.

Example: the shell in SCREEN calls ssh, and SCREEN is again used in the remote machine. To detach the session in the remote SCREEN, press C-A a d.

BASH’s ‘read’ built-in supports '\0' as delimiter

I thought it was impossible to use '\0' as a delimiter in bash, but noticed yesterday that Gentoo’s ebuild.sh had pipelines like this:
find ..... -print0 |
while read -r -d $'\0' x; do
# Do something with file $x

This makes it possible to handle any strange filenames correctly, even if the filename contains newline ('\n') or carriage return ('\r') characters. (Some other commands, including sort and xargs, have options to make null character the delimiter based on the same reason.)

Because BASH internally uses C-style strings, in which '\0' is the terminator, read -d $'\0' is essentially equivalent to read -d ''. This is why I believed read did not accept null-delimited strings. However, it turns out that BASH actually handles this correctly.

I checked BASH’s souce code and found the delimiter was simply determined by delim = *list_optarg; (bash-3.2/builtins/read.def, line 296) where list_optarg points to the argument following -d. Therefore, it makes no difference to the value of delim whether $'\0' or '' is used.

SSH without password

Log into the client end and run ssh-keygen (In some systems parameter -t rsa is needed).

Then append ~/.ssh/id_rsa.pub (client end) to file ~/.ssh/authorized_keys (create it if not present) at the server end.


The Uncertainty Principle

If we define a global constant in C++:
const int x = 2;
The typical behavior of an optimizing compiler is to allocate memory for x only if its address is explicitly taken with an & operator or it is bound to a reference. (Otherwise constant propogation is sufficient.)

Now let’s assume we can only change the codes, compile and run them. Disassembly is not allowed. (That’s like physics - we can only do experiments and observe the results.) Then we are unable to find out whether x actually has an address. The only way we can detect it is to take its address and see whether there’s going to be a compiling error. But this process creates an address for it. (In physics, when we are measuring the position and momentum of a particle, we are changing its position and/or momentum.)

A similar thing is about the default constructor, default copy-constructor, default copy-assignment and default destructor. Some books say that a class always has them (in semantics); some books say compilers create them on demand (in implementation). Both are right - we cannot detect this in program.

Time (if any) before the Big Bang is irrelavent to our universe, so we can assert time did not exist before the Big Bang for a simpler model. Likewise, we can assert (semantically) a constant always has an address, and a class always have the four things, for a simpler model.

Do What The Fuck You Want To Public License

WTFPL stands for “Do What The Fuck You Want To Public License”. It is like GPL or BSD license or any other public license you may have heard of, but has no restrictions, allowing you to “do what the fuck you want to.”

                    Version 2, December 2004

 Copyright (C) 2004 Sam Hocevar
  14 rue de Plaisance, 75014 Paris, France
 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.



This is NOT joking. You can find software licensed under WTFPL in almost all major Linux distributions. The best known one may be the ASCII-art library libcaca, which is used by the well-known player mplayer. (In Gentoo you can find the text of the license at /usr/portage/licenses/WTFPL-2.)

You may want to ask if there is any difference from WTFPL to public domain. The authors explain that the definition of public domain varies from jurisdiction to jurisdiction, and it is unclear in some countries whether works can be in public domain unless its authors have been dead for 70 years, but it is absolutely clear in most countries you have the right to choose a license for your works.

[Unlike other posts licensed under Creative Commons, this post is licensed under the Do What The Fuck You Want To Public License.]


I use an init script to log in my ISP. The script is like this
wget -O - --post-data 'username=...&password=...' 'http://....' |
html2text | tee /tmp/$$.txt
fgrep -q 'already logged in' /tmp/$$.txt || exit 1
unlink /tmp/$$.txt
(The username and password are public in this building, so I need not worry about the clear-text password.)

It was strange that /tmp/$$.txt apparently contained the string “already logged in” but the script always exited abnormally (fgrep fails).

I finally found the reason by opening /tmp/$$.txt with bvi (a vi-style hexadecimal editor): the string in the file was actually like this: “You a\bare alr\bread\bdy logged\bd in.” (“\b” stands for backspace character.) That’s why fgrep could not find the string..

html2text sucks.

MATLAB xcb error

XCB breaks MATLAB (probably also other Java applications):
MATLAB: xcb_xlib.c:50: xcb_xlib_unlock: Assertion `c->xlib.lock' failed.
Either of the two workarounds works for me:
(1) If the libxcb version is ≥1.1, export LIBXCB_ALLOW_SLOPPY_LOCK=1 before running the broken application.
(2) Recompile libxcb with CFLAGS="-DNDEBUG". This macro disables assertions.

Workaround 2 uses some kind of brutal force, and in most cases Workaround 1 should be preferred.

[ Another workaround is found here. I think it works though I didn’t try it. However this uses even more brutal force. ]

[1] Gentoo Forum thread: xorg-server-1.3.0 + xcb breaks java ?
[2] LFS documentation on libxcb

C++0x draft finished

Only bugfixes, no new feature, will be added to the standard from now on.

Good. It is almost certain it will be called C++ 2009.

As I see, many new features will bring great convenience to programming. But... C++ will appear far more complicated and difficult and perhaps unreasonable to a newbie. It’s already complicated enough now...

Ten years ago C9x became C99, and now C++0x is becoming C++09. But there will be one certain difference: No major compiler completely implements C99 even today; however, every actively developed C++ compiler seems to be planning to add C++09 support as immediately as possible.

[1] September 2008 ISO C++ Standards Meeting: The Draft Has Landed, and a New Convener

Determine the existence of a file in Makefile

Combine "wildcard" and "ifeq". For example,
ifneq "$(wildcard Makefile.inc)" ""
include Makefile.inc
GNU Make is powerful!

Always start denyhosts with sshd

Denyhosts is a small tool that frequently checks SSH daemon logs for incoming requests and put suspective IPs into /etc/hosts.deny.

For some reason, denyhosts was not running in recent days in my machine. (It should be automatically started at boot time, but was not.) Today I restarted it, and 7 IPs were immediately banned. They are from all around the world: 1 from US, 1 from Germany, 1 from Turkey, 1 from Armenia, and the rest 3 from China (respectively Xiamen University, Tianjin Netcom, and Qingdao Guangdian).

I then checked /var/log/messages, and found 5236 attacks in the last 5 days.

Yes, hackers all around the world are doing all kinds of brute-force attacks. Last summer, I found someone was using my anonymous proxy at port 3128, which had been open for just a few hours, to send hundreds of spams.


I wanted to find out if remote X creates a lot of network flows, so I logged into a remote computer with "ssh -Y", started xclock, and then typed tcpdump. Then screen began scrolling up crazily like this:
13:21:00.694367 IP xxx.xxx.xx.xx.45762 > . ack 60640 win 2003 <nop,nop,timestamp 191668683 75287130>
13:21:00.694430 IP > xxx.xxx.xx.xx.45762: P 70416:70464(48) ack 113 win 501 <nop,nop,timestamp 191668683 75287200>
Was X sending/receiving lots of data even if it seems to be idling? It shouldn't be so silly.. And... Finally I realized what a big mistake I had made... It was like putting a microphone against a loudspeaker...

SSH with X

Just successfully started FCITX and typed Chinese in OpenOffice remotely..

X11 forwarding should be first enabled both at the server and client ends.

At the server end, put "X11Forwarding yes" in /etc/ssh/sshd_config, restart SSH daemon and it should be able to forward X11 requests.

At the client end, connect with "ssh -X " or "ssh -Y " (if ssh -X fails..). Alternatively, SSH client can be configured to turn on X11 forwarding automatically. Put in /etc/ssh/ssh_config the following lines:
Host *
  ForwardX11 yes
  ForwardX11Trusted yes
The last line is not needed if "ssh -X" works. In some circumstances only "ssh -Y" does, then ForwardX11Trusted is necessary.

ps1. If network is slow, "-C" (compress) may help.
ps2. X must be running with "-nolisten" argument, which (I guess) is the default in most distributions.


In my Core 2 running 64-bit Linux, it insists on compiling one of the Fortran sources with “gfortran -march=athlon64 -mfpmath=sse -msse2 -m3dnow ...”, regardless of the FFLAGS environment variable. (Other Fortran files honor FFLAGS, nevertheless...)

It does not matter much if you insist on use “-march=athlon64”, but “-m3dnow” is really a problem since Intel never ever supported 3DNow!

Yuking resumes FCITX development


FCITX (Free Chinese Input Toy for X) was one of the two major Chinese input methods in Linux. Yuking mentioned in his recent post that he had just learned to use SVN. It was amazing he had created such a successful tool without using any version control system... (The source files contain approximately 30k lines)

The codes were criticized to be "amateur" - mainly based on his use of Chinese configuration files and Chinese comments (both in GBK, not UTF-8). These criticism directly caused Yuking to stop development last year. But I still have no idea why it is not reasonable to use Chinese character in a Chinese input method...

Disk size needed to compile OpenOffice

Gentoo today stabilized openoffice 3.0. I then emerged it in two systems. OpenOffice 3 now supports parallel building, so there should be a speedup compared with 2.4 in an multi-core system.

x86 laptop: debugging is completely disabled. About 5 GiB.

amd64 desktop: CFLAGS="... -ggdb"; FEATURES="splitdebug". More than 11GiB!

Too Smart Router

I got a router between the WAN port and my computer. It seems it is just so "smart" that it, in the name of security, is preventing me from working properly...

If I don't use the router, I can easily connect to my computer using SSH and the connection still is active after being idle for an hour, which should be normal when you log in remotely.

With the router, I told it to redirect incoming requests to port 22 to my desktop, which works actually. HOWEVER, the router not only kills connections that has been idle for just a few minutes, but also rejects further requests from the same IP for a long time! So I now have a bash script:
 #! /bin/bash
until read -t10; do
Once I finish something in SSH, I run this script. It sends several bytes every ten seconds so that the router won't consider the connection idle... I'm wondering what better workaround I can use (other than disconnecting frequently...)? I'm almost sure the router can't be configured so that it allows a connection to be idle for a long time..

[Update Oct 26: A better solution may be sending null bytes periodically, like what PuTTY does. This is usually called "anti-idle".]

A similar problem happened when I was transferring files from my laptop to my desktop (both connected to LAN ports of the router) with SCP. I issued SCP commands about ten times in several minutes, and further connections were rejected too. Is it possible to be again the router's fault? (SSH daemon had no reason to do so, I think.)

Why VirtualBox window is transparent...

I have been using Compiz Fusion and VirtualBox for a while. They were both working well except I could not switch VirtualBox to fullscreen or seamless mode. I did not change any setting either in Compiz Fusion or VirtualBox, but these two days all black pixels have become transparent. What's the problem?... (If I shut down Compiz Fusion, VirtualBox displays coreectly.)

mov %edi, %edi

Here is a simple C function:
long foo (unsigned a, unsigned b)
    return ((long)b<<32)|a;
Compile it with an x86-64-targeted GCC with proper optimizations enabled (-O2 for example), you get the following instructions (in AT&T-style assembly):
        movq    %rsi, %rax
        mov     %edi, %edi
        salq    $32, %rax
        orq     %rdi, %rax
Pay attention to the red line. Literally it means assigning the value of register edi to register edi. Five years ago, anybody would agree this instruction does nothing like nops. But in an x86-64 system, this is not the case.

In x86-64 assembly, any instruction with a 32-bit register as its destination zeroes the higher 32 bits of the corresponding 64-bit register at the same time. Consequently, the function of ‘mov %edi, %edi’ is zeroing bits 32 to 63 of register rdi while leaving the lower 32 bits (i.e., register edi) unchanged.

One may want to rewrite it with a more intuitive and instruction:
andq $0xffffffff, %rdi
But this does NOT assemble! Because $0x00000000ffffffff is not representable in signed 32-bit format, but 64-bit immediates are currently allowed only in mov instructions whose destination is a general-purpose register (such a mov is usually explicitly written as movabsq). So if one must use and, one need something like this:
movl $0xffffffff, %eax
andq %rax, %rdi
Remember the zeroing rule for operations on 32-bit registers, so ‘movl $0xffffffff, %eax’ is equivalent to ‘movabsq $0xffffffff, %rax’...

X86-64 assembly really is too ugly, at least in this sense...

[1] Gentle Introduction to x86-64 Assembly

Shrink an LVM partition

Gentoo’s Documentation says it is easier to increase the size of an LVM partition than to shrink it, so they recommend starting with smaller partitions and then increase them as needed.

Of course they are not saying shrinking is impossible, but only less easy. The most important thing is the FS must be reduced BEFORE the volume, or the FS will get damaged.

Example: Shrink partiton /dev/vg/home with ext3 filesystem from 30G to 12G:
e2fsck /dev/vg/home (resize2fs requires a check before resizing)
resize2fs /dev/vg/home 10G
(resize FS to 10G)
lvreduce -L12G /dev/vg/home
(reduce partition)
resize2fs /dev/vg/home (extend FS to the whole partition)

Someone (I’m not sure who..) recommended doing two resizes like this claiming it is safer.

Another VMware problem

Forgot about this when writing the previous post..

I had an error like this when trying to start VMware Workstation in a Linux host:
*** attempt to put segment in horiz list twice
/opt/vmware/workstation/lib/bin/vmware: symbol lookup error: /usr/lib/libglade-2.0.so.0: undefined symbol: g_return_if_fail_warning

The workaround is to export an environment variable before running vmware:

The GTK libraries in my system is binary incompatible with the ones used by the VMware team, so VMware must use the library files shipped with it instead of those in my system. Similar compatibility problems are not rare when it comes to a closed-source application that is dynamically linked against an open-source library...

[1] HOWTO: Install vmware workstation 6.0.3 build 80004 (March 14) on Sabayon x86-3.5 Loop2-r2
[2] VMWARE_USE_SHIPPED_GTK=force vmware

Arrow keys not working in VMware

Arrow keys (and also Ctrl, Win, etc.) don't work in VMware if running in KDE. This should be an upstream bug.

Workaround: Add this line to ~/.vmware/config (create it if necessary) and restart VMware:
xkeymap.nokeycodeMap = true
VMware will display a warning about keyboard layout. Simply ignore it.


SEEK_* Problem with MPICH2

This is a frequently encountered error when writing MPI programs in C++.
/usr/include/mpicxx.h:26:2: error: #error "SEEK_SET is #defined but must not be for the C++ binding of MPI"
/usr/include/mpicxx.h:30:2: error: #error "SEEK_CUR is #defined but must not be for the C++ binding of MPI"
/usr/include/mpicxx.h:35:2: error: #error "SEEK_END is #defined but must not be for the C++ binding of MPI"

I remember (not very sure) it was MPICH2 that introduced this problem. It was not present in MPICH1.

This happens if <mpi.h> is inlcuded AFTER some system headers like <stdio.h> and <iostream>. The workaround is simple: always include <mpi.h> first in any C/C++ source that uses MPI APIs. (Another workaround is to pass -DMPICH_IGNORE_CXX_SEEK to mpicxx, but it seems this has other drawbacks. Do this only if you are unable to modify the sources.)

This certainly should be considered a bug of MPICH2: SEEK_SET, SEEK_CUR, and SEEK_END are constant symbols required by the ANSI C standard, but MPICH2 has global variables with exactly the same names. MPICH2 has not changed this, though they apparently have realized this problem for long. (Otherwise they could not have introduced MPICH_IGNORE_CXX_SEEK. Probably they have binary compatibility concerns?)

Jumbled Characters after Catting a Binary File

When this happens, simply press Ctrl-V Ctrl-O Ctrl-M. Or alternatively, type "reset" and Return (Enter).

A terminal interpretes 0x0e byte as "activates the G1 character set", and 0x0f as "activates the G0 character set". The characters we read are in the G0 set. So, if there is no byte 0x0f after the last 0x0e in a binary file, everything will be shown in the unreadable G1 set, including the next shell prompt.

How does Ctrl-V Ctrl-O Ctrl-M work?
Ctrl-V is an 'escape character' - the next keystroke will always be interpreted as a literal character; Ctrl-O is 0x0f; Ctrl-M is carriage return. So the shell gets the command "\x0f" and outputs the error message "bash: \x0f: command not found". The byte 0x0f in this message turns the active character back to the readable G0.

G1 character set is not often used these days. Konsole chooses not to implement it at all, so we never have this problem in Konsole.

Department Computers

The department computer and network administrators are completely of the opposite kind of people from me. They installed everything I dislike, and almost nothing I like...
  • I dislike Ubuntu, but most of the so-called “Unix” machines are Ubuntu. (The rest are Solaris.)
  • I like bash (as most Unix-like users do these days, I bet...), but their default shell is tcsh. Perhaps this is a convention inherited from antediluvian days.
  • They have GNOME, Xfce, fvwm, Sawfish and Fluxbox installed. The only major DE/WM missing is KDE, which is my favorite.

The first time I tried to print something, it was sent to a printer in a lab 50 yards away, despite the fact that there was one only 2 yards from me. I needed to set the PRINTER environment variable so that lpr knew I wanted to use the printer in my office.

If I were using KDE, I would have finished this in 20 seconds, by catting a 2-line file to ~/.kde/env. But it took me 20 minutes to find its counterpart in GNOME, and then another 5 minutes to find out whether I should write the script ~/.gnomerc in Bourne Shell grammar or C Shell grammar. The answer is Bourne Shell grammar. Though the default shell is tcsh, ~/.gnomerc is always interpreted by /bin/sh, which is a symlink to dash (not bash) in Ubuntu and latest version of Debian... Humph.....

First Post

Welcome. This is my very first post here. I plan to put here something about Linux and programming (mainly in C, occasionally other languages) here. I do this mainly for my future reference, but hopefully will also benefit those who are googling for a solution for some problem.

I am a user of Gentoo Linux (i686 and AMD64, at home) and Ubuntu Enterprise (i686, at lab) (and occasionally Solaris), and an everyday user of C/C++. I am learning OpenGL and OpenMP at present.

I have had a similar weblog for exactly one year at another place (in Simplified Chinese), but have just decided to stop updating that one and to move here. (This blog will be all in English.)

I am also keeping another weblog (in Simplified Chinese), which covers everything (that interests me) but technical posts.