2012-09-22

How to change the volume label to lowercase on an USB stick, memory card or any VFAT filesystem on Ubuntu Lucid

This blog post explains how to change the volume label to lower case on an USB stick, memory card or any other VFAT filesystem. The instructions given were verified for Ubuntu Lucid, but they may work on other Linux systems as well.

On the web some people claim it's not possible, but indeed it is. On the web there are instructions how to change the volume label with GParted or mlabel (part of Mtools) and palimpsest (Disk Utility), but none of them work, because these tools always convert lowercase to uppercase before setting the label. Nautilus, the default file manager for Ubuntu doesn't support changing the volume label at all.

mkdosfs (mkfs.vfat) lets the user specify the volume label using the -n flag, and lowercase letters are kept lowercase, but this tool recreates the filesystem, so all data will be lost.

The non-destructive solution below is a combination of the mlabel and dosfslabel command-line tools.

  1. Connect the device to the computer if not already connected.
  2. Open a terminal window.
  3. Run sudo blkid | grep ' TYPE="vfat"' and </proc/mounts grep ' vfat ' to figure out the name of the device (e.g. /dev/sdb1). Look around in /media etc. to confirm you have picked the right device. If unsure, unplug it, run the commands again, see it disappear, plug it back, and run the commands again.
  4. Unmount the device by running umount /dev/sdb1 (substituting /dev/sdb1 with the name of the device found above). If it was mounted, and the unmount failed, then close some windows, kill some programs (e.g. sudo fuser -m /dev/sdb1), and try unmounting again.
  5. Run sudo env MTOOLS_SKIP_CHECK=1 mlabel -i /dev/sdb1 ::x (substituting /dev/sdb1 with the name of the device found above). If the system can't find mlabel, then install it by running sudo apt-get install mtools , and try again.
  6. Run sudo dosfslabel /dev/sdb1 MyLabel (substituting MyLabel with the desired label and /dev/sdb1 with the name of the device found above). Ignore any warnings about boot sector differences. If the system can't find dosfslabel, then install it by running sudo apt-get install dosfstools , and try again.
  7. Run sudo blkid | grep ' TYPE="vfat"' , and examine its output to verify that the label has been changed properly.
  8. Optionally, unplug the device, and then plug it back in. The system will recognize it, and mount it under /media/MyLabel, without converting lowercase letters in the volume label to uppercase.

Please note that there is an 11 character limit on the length of a VFAT volume label. If you specify a longer label, it will be truncated. There is another restriction: the label can contain only (some) ASCII characters: accented letters etc. won't work.

2012-09-04

How to unlock an Android phone using adb if you know the password

This blog post explains how to unlock an Android phone using adb if you know the password. This can be useful if the touch screen of your phone is broken.

If you don't know the password, try any of the 9 methods in the article http://joyofandroid.com/how-to-unlock-android-phone/ instead.

Prerequisites:

  • You have a computer running Windows, Mac OS X or Linux.
  • You have a USB cable with which you can connect the phone to the computer.
  • USB debugging has been enabled on the phone. You can enable it in the Settings / Development menu (but you need a working touch screen for that).
  1. Install the adb command-line tool. It's part of the Platform SDK Tools SDK package. First download the Android SDK, then run the tools/android GUI tool, select Platform SDK Tools and install. The adb binary will be downloaded to platform-tools/adb .
  2. On Linux, follow these steps to make sure that your user has the permission to access the phone.
  3. Don't connect your phone yet to the computer via USB.
  4. Run adb devices and verify that it doesn't see the phone.
  5. If not enabled yet, enable USB debugging on the phone, in the Settings / Development menu.
  6. Connect the phone to your computer using an USB cable.
  7. Run adb devices and verify that it sees your phone.
  8. You will have to run the following two commands very quickly, i.e. faster than the screen blanking time on the phone.
  9. Run adb shell input text PASSWORD, replacing PASSWORD with your Android unlock password.
  10. Run adb shell input keyevent 66 to simulate pressing the Enter key. (See this page for event codes of other keys.)

2012-08-14

How to use duplicity on Ubuntu Lucid to make backups to Google Drive

This blog post is a tutorial explaining how to install duplicity to an Ubuntu Lucid system and how to make backups to Google Drive using duplicity.

Installation

Run these commands (without the leading $) in a terminal window:

$ sudo apt-get install python-setuptools python-dev gcc libc6-dev gnupg librsync-dev screen
$ sudo easy_install gdata
$ sudo easy_install http://code.launchpad.net/duplicity/0.6-series/0.6.19/+download/duplicity-0.6.19.tar.gz
$ duplicity --version
duplicity 0.6.19

Starting a backup

It's recommended to issue the following command from screen, so they don't get aborted if there is a problem with the terminal window.

Example terminal window interaction to start a backup:

$ duplicity ~/Documents gdocs://USERNAME@gmail.com/documents.backup
Password for 'USERNAME@gmail.com':
Local and Remote metadata are synchronized, no sync needed.
Last full backup date: none
GnuPG passphrase:
Retype passphrase to confirm:
No signatures found, switching to full backup.
--------------[ Backup Statistics ]--------------
...
Errors 0
-------------------------------------------------

When duplicity asks you for your Google Account (@gmail.com) password, you have to type your regular password, i.e. the password you use to log in to Gmail and Google Drive, unless you are using 2-step authentication for logging in. In that case you need to generate an application-specific password (at the bottom of this page), and copy-paste it to duplicity.

2012-08-02

How to format a double with 5 digits of precision in pure Java

This blog post shows pure Java code to format a double with 5 digits of precision, i.e. non-scientific notation, rounded to at most 5 digits after the decimal point, can be very long in front of the decimal point.

Java's built-in NumberFormat class can be used (see its invocation in the check method below), however that class not available in all JVMs (e.g. Avian). Another option is to convert the double to a string (e.g. "" +d or Double.toString(d) or String.valueOf(d)), and manually analyze the string to convert the scientific notation (e.g. 123.456e78) to decimal notation (see the numberFormat5assumes method below). However, in some JVMS (e.g. Avian) Double.toString(d) returns only 5 digits at most in total, so it loses lots of precision. To work around this, we can convert the double to a long (but divide large doubles first so they would fit), convert the long to a String, and add the decimal point manually (see the numberFormat5 method in the code below). This last solution is inaccurate for large doubles (because of the divisions by powers of 10 involved).

For a more precise, but much more complicated implementation, see dtoa.java, see more on this StackOverflow page.

import java.text.NumberFormat;
import java.util.Locale;

public class nf {
  // This implementation assumes that Double.toString returns the most accurate
  // possible strings.
  public static String numberFormat5assumes(double d) {
    if (Double.isNaN(d)) return "\ufffd";
    if (Double.isInfinite(d)) return d < 0 ? "-\u221e" : "\u221e";
    if (-1 < d && d < 1) {
      boolean isNegative = d < 0 || (d == 0 && "-0.0".equals("" + d));
      if (isNegative) d = -d;
      String sa = "0." + ((100000 + (int)(.5 + d * 100000)) + "").substring(1);
      int i = sa.length();
      while (i > 0 && sa.charAt(i - 1) == '0') {
        --i;
      }
      if (i == 2) i = 1;
      sa = sa.substring(0, i);
      return isNegative ? "-" + sa : sa;
    } else {
      String s = "" + d;
      char c;
      int i = s.length() - 1;
      while (i > 0 && (c = s.charAt(i - 1)) != 'e' && c != 'E') {
        if ((c < '0' || c > '9') && c != '.' && c != '-') {
          throw new RuntimeException("Bad double: " + s);
        }
        --i;
      }
      int j = i;
      int e = 0;
      if (i > 0) {
        while (j < s.length()) {
          e = 10 * e + s.charAt(j++) - '0';
        }
        --i;
      } else {
        i = s.length();
      }
      char o[] = new char[s.length() + e];
      j = 0;
      int w = 0;
      if (s.charAt(0) == '-') {
        o[w++] = '-';
        ++j;
      }
      int t = j;
      while (j < i) {
        if ((c = s.charAt(j)) == '.') {
          t = j + 1;
        } else {
          o[w++] = c;
        }
        ++j;
      }
      if (j - t > e) {
        i = w++;
        while (j - t > e) {
          o[i] = o[i - 1];
          --i;
          ++t;
        }
        o[i++] = '.';
        if (w - i > 5) {
          w = i + 5;
          if (o[i + 5] >= '5') {  // Round up.  (Should be >5.)
            j = i + 5;
            while (j > 0) {
              --j;
              if (o[j] == '.') continue;
              if (o[j] == '-') break;
              if (o[j] != '9') { ++o[j]; j = -1; break; }
              o[j] = '0';
            }
            if (j == 0) {
              if (o[j] == '-') ++j;
              o[j++] = '1';
              while (j < w) {
                if (o[j] == '.') {
                  o[j++] = '0';
                  o[j++] = '.';
                  i = j;
                  break;
                } else {
                  o[j++] = '0';
                }
              }
              w = j;
            }
          }
        }
        while (w > i && o[w - 1] == '0') {
          --w;
        }
        if (w == i) {  // "." -> "".
          --w;
        }
      } else {
        while (j - t < e) {
          o[w++] = '0';
          --t;
        }
      }
      return new String(o, 0, w);
    }
  }

  // This implementation doesn't use Double.toString at all (but it uses the
  // `(long)aDouble' conversion). It's a bit less accurate (can be as few as
  // 16 correct digits out of 21) for very large doubles (abs(d)>=1e13).
  public static String numberFormat5(double d) {
    if (Double.isNaN(d)) return "\ufffd";
    if (Double.isInfinite(d)) return d < 0 ? "-\u221e" : "\u221e";
    boolean isNegative = d < 0 || (d == 0 &&
        "-0.0".equals("" + d) || "-0".equals("" + d));
    if (isNegative) d = -d;
    String s;
    if (d >= 10000000000000.0) {  // 13 zeros.
      // 9223372036854775807 == Long.MAX_VALUE.
      // 1000000000000000000 has 13+5 zeros.
      // TODO: Instead of 9.223e13, check for 9.223372036854775807e13.
      int c = 0;
      // These divisions below are a bit inaccurate, but doing them accurately
      // would need >1000 lines of code. Example inaccuracies:
      //
      // -5.555333333333333E20: the first 18 digits (out of 21) are correct.
      // 1.7976931348623157E308: the first 16 digits are correct.
      while (d >= 9.223e25)   { d /= 10000000000000.0; c += 13; }
      if (d >= 9.223e24)      { d /= 1000000000000.0; c += 12; }
      else if (d >= 9.223e23) { d /= 100000000000.0; c += 11; }
      else if (d >= 9.223e22) { d /= 10000000000.0; c += 10; }
      else if (d >= 9.223e21) { d /= 1000000000.0; c += 9; }
      else if (d >= 9.223e20) { d /= 100000000.0; c += 8; }
      else if (d >= 9.223e19) { d /= 10000000.0; c += 7; }
      else if (d >= 9.223e18) { d /= 1000000.0; c += 6; }
      else if (d >= 9.223e17) { d /= 100000.0; c += 5; }
      else if (d >= 9.223e16) { d /= 10000.0; c += 4; }
      else if (d >= 9.223e15) { d /= 1000.0; c += 3; }
      else if (d >= 9.223e14) { d /= 100.0; c += 2; }
      else if (d >= 9.223e13) { d /= 10.0; c += 1; }
      char cs[] = new char[c];
      while (c > 0) {
        cs[--c] = '0';
      }
      double e = d * 100000.0 + 0.5;
      s = (long)e + new String(cs);
    } else {
      // We have to introduce a temporary variable (e) here for i386 gcj-4.4
      // on Ubuntu Lucid (4.4.3-1ubuntu4.1), without optimization flags.
      // Without this temporary variable it would convert 0.834375 to 83437
      // instead of the correct 83438.
      //
      //   gcj-4.4 -o nf --main=nf nf.java && ./nf
      double e = d * 100000.0 + 0.5;
      s = (long)e + "";
    }
    int i = s.length();
    int j = s.length() - 5;
    while (i > j && i > 0 && s.charAt(i - 1) == '0') {
      --i;
    }
    if (i == 0) {
      s = "0";
    } else if (i == j) {  // Found an integer.
      s = s.substring(0, j);
    } else if (j <= 0) {  // Found a number between 0 and 1.
      s = "0.00000".substring(0, 2 - j) + s.substring(0, i);
    } else {
      s = s.substring(0, j) + "." + s.substring(j, i);
    }
    return isNegative ? "-" + s : s;
  }

  public static void check(double d) {
    NumberFormat nf = NumberFormat.getInstance(Locale.US);
    nf.setMinimumFractionDigits(0);
    nf.setMaximumFractionDigits(5);
    nf.setGroupingUsed(false);
    String a = nf.format(d);
    String b = numberFormat5(d);
    if (!(a.equals(b))) {
      System.err.println(d + ": " + a + " != " + b);
    }
    System.out.println("    check2(" + d + ", \"" + a + "\");");
  }

  public static void main(String[] args) {
    check(42.0);
    check(42.7);
    check(-42.7);
    check(-42.7654321);
    check(-555533333333333333342.7654321);  // numberFormat5 is inaccurate.
    check(Double.NaN);  // FYI gcj-4.4 NumberFormat emits "NaN', openjdk-6 emits "\ufffd".
    check(Double.MIN_VALUE);
    check(Double.MAX_VALUE);  // numberFormat5 is inaccurate.
    check(Double.NEGATIVE_INFINITY);
    check(Double.POSITIVE_INFINITY);
    check(-0.000000034);
    check(0.0);
    check(-0.0);  // FYI gcj-4.4 NumberFormat emits "0", openjdk-6 emits "-0".
    check(-0.7654321);
    check(-0.3456789);
    check(-0.34);
    check(-0.056);
    check(0.0078);
    check(123.456);
    check(-123.456);
    check(-123.456789);
    check(-123.450009);
    check(123.450005);  // NumberFormat is inaccurate: 123.45 != 123.45001.
    check(123.450006);
    check(123.499996);
    check(-123.450003);
    check(-99.999995);
    check(999.999995);
    check(-123.999999);
    check(-123.899999);
    check(0.834375);
    check(-0.834375);
  }
}

2012-06-30

How to compile Java programs to stand-alone executables for Windows, Linux etc.

This blog post explains how to compile Java programs (e.g. a set of .java, .class and .jar files) to stand-alone binary executables which run on Linux, Windows etc. Each executable is platform-specific, but executables can be generated for many different platforms. A JVM or JRE on the target system is not required to run the executable.

The main idea is to use GCJ, The GNU Compiler for Java to generate the executable. For example, do it like this on Ubuntu Lucid, to generate a Linux executable:

Linux

$ cat >Hello.java <<'END'
public class Hello {
  public static void main(String args[]) {
    System.out.println("Hello, World!");
  }
}
END
$ sudo apt-get install gcj
$ gcj -v
Target: x86_64-linux-gnu
Configured with: ...
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-1ubuntu4.1) 
$ gcj --main=Hello -g -o hello Hello.java
$ ./hello
Hello, World
$ $ ls -l hello                                                     
-rwxr-x--- 1 user group 13846 2012-06-30 15:20 hello
$ ldd ./hello
        linux-vdso.so.1 =>  (0x00007fff01fff000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fb352663000)
        libgcj.so.10 => /usr/lib/libgcj.so.10 (0x00007fb34f4fc000)
        libm.so.6 => /lib/libm.so.6 (0x00007fb34f278000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00007fb34f05b000)
        librt.so.1 => /lib/librt.so.1 (0x00007fb34ee53000)
        libz.so.1 => /lib/libz.so.1 (0x00007fb34ec3b000)
        libdl.so.2 => /lib/libdl.so.2 (0x00007fb34ea37000)
        libc.so.6 => /lib/libc.so.6 (0x00007fb34e6b4000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fb35289a000)

If you don't want the executable to depend on libgcj, you can prepend -static-libgcj to the gcj command-line, but that won't work with the stock gcj package on Ubuntu Lucid, because libgcj.a was not included in the package. However, if you compile your own GCC (and enable Java), that will support -static-libgcj .

Windows

GCJ also runs on Windows: in Cygwin and MinGW. (You can generate Win32 executables with it.) GCJ 4.4.0 was released as part of MinGW, but GCJ's setup process is mostly undocumented and contains lots of gotchas. You can't just install the latest MinGW, because after GCC 4.4, MinGW doesn't include GCJ in GCC. So, for your convenience, I created a ZIP archive containing GCJ 4.4.0 for Windows (using MinGW) and all its dependencies. Just download http://pts-mini-gpl.googlecode.com/files/wgcj44-r1.zip, extract it, and start running bin/gcj .

It is a working GCJ (GNU Java Compiler) 4.4.0 compiled for Win32. You can use it to compile .java and .class files to Win32 .exe files. The generated .exe is stand-alone, it doesn't need a JDK or JRE, and it can run on any Win32 system. (There are some bugs, restrictions and incompatibilities between e.g. OpenJDK and GNU ClassPath, the Java standard library GCJ 4.4 uses. So your Java programs won't work out-of-the-box, but it's possible to make small porting changes to make them work.)

It has been tested and found working on Windows XP and Wine 1.2 on Ubuntu Lucid. So you don't need a Windows machine in order the be able to release a Windows .exe version of your Java program. Just run the GCJ 4.4.0 above using Wine on Linux (or Mac OS X etc.) to generate the .exe .

The binaries are from MinGW (thus they are free software under the GPL, parts under different free licenses, see MinGW's license). Most of the files were extracted from archives downloaded from this MinGW download page.

Example invocation in debug mode (with line numbers in exception stack traces):

bin\gcj -static-libgcj -static-libgcc --main=Prog -g -o prog.exe P*.java

This will generate a 44 MB binary. It's pretty huge, but it contains a whole JRE and the Java standard library with debug symbols.

Example invocation in optimized mode (without line numbers in exception stack traces):

bin\gcj -static-libgcj -static-libgcc --main=Prog -s -O2 -o prog.exe P*.java

This will generate a 13 MB binary.

If you get ExceptionInInitializerError when trying to use the classes Date, SimpleDateFormat or Calendar, e.g.

Exception in thread "main" java.lang.ExceptionInInitializerError
   at java.lang.Class.initializeClass(t.exe)
   at java.util.Calendar.getInstance(t.exe)
   at t.main(t.exe)
Caused by: java.lang.NullPointerException
   at java.io.InputStreamReader.read(t.exe)
   at java.io.BufferedReader.fill(t.exe)
   at java.io.BufferedReader.readLine(t.exe)
   at java.util.Properties.load(t.exe)
   at java.util.Properties.load(t.exe)
   at java.util.Calendar.(t.exe)
   at java.lang.Class.initializeClass(t.exe)
   ...2 more

, then add libgcj_properties.a like this (without the line break):

bin\gcj -Wl,--whole-archive -lgcj_properties.a -Wl,--no-whole-archive
    -static-libgcj -static-libgcc --main=Prog -s -O2 -o prog.exe P*.java

You can add the bin directory to the PATH. After that you can invoke gcj directly (without the bin\).

2012-06-28

pdfsizeopt released for Windows

This blog post is to announce that pdfsizeopt, a PDF file size optimizer is now available for Windows (Win32) systems. See the Windows installation instructions. Previously pdfsizeopt was available only on Unix systems, with Linux and Mac OS X explicitly supported.

pdfsizeopt is a program for converting large PDF files to small ones. More specifically, pdfsizeopt is a free, cross-platform command-line application (for Linux, Mac OS X, Windows and Unix) and a collection of best practices to optimize the size of PDF files, with focus on PDFs created from TeX and LaTeX documents. pdfsizeopt is written in Python, so it is a bit slow, but it offloads some of the heavy work to its faster (C, C++ and Java) dependencies. pdfsizeopt was developed on a Linux system, and it depends on existing tools such as Python 2.4, Ghostscript 8.50, jbig2enc (optional), sam2p, pngtopnm, pngout (optional), and the Multivalent PDF compressor (optional) written in Java.

2012-04-22

How to disable new tab animation in firefox

This blog post explains how to disable the short animation when a new tab is opened in Mozilla Firefox. The solution was tested with Firefox 11 on Linux, but it should work in all versions between 4 and 11, on any operating system.

This question has been asked and answered many times on the web, and most of the answers suggest toggling browser.tabs.animate to false in about:config. However, this disables animation only if there are a few tabs so that horizontal scrolling is not needed. To disable new tab scrolling animation as well, toggle toolkit.scrollbox.smoothScroll to false as well. The change takes effect in windows you open afterwards.

2012-04-16

How to change the escape key (^A) in screen without typing it

This blog post explains how to change the escape key (Ctrl-A by default) in an instance of GNU Screen if you are unable to type that key (possibly because of a malfunctioning terminal emulator).

To change the escape key to Ctrl-B, run this command (without the leading $) within the screen you want to affect:

$ screen -S "$STY" -X escape "$(perl -e 'print"\cB"x2')"

You can change back to Ctrl-A by changing the \cB in the code above to \cA. Other escapes such as Ctrl-W and even Ctrl-C also work.

You can also change the escape key remotely (i.e. on the same machine, but outside the screen) by specifying the PID or the name or both (of the form PID.NAME) of the screen to affect instead of $STY above. Use

$ screen -list

to obtain the list of PIDs and names of currently running screens. If you have given your screen session the name foo by starting it as

$ screen -S foo
, then the command to change the escape key to Ctrl-B is the following:
$ screen -S foo -X escape "$(perl -e 'print"\cB"x2')"

All these changes take effect immediately.

2012-03-31

Announcing mmshget: mmsh:// (MMS-over-HTTP) video stream downloader and reference implementation

This blog post is to announce mmshget, a command-line Python script to download streaming videos of the mmsh:// (MMS-over-HTTP) protocol, in .wmv (or .asf) format. mmshget can also be used as an easy-to-understand, simple, client-side, partial reference implementation of the mmsh:// protocol.

Download the Python script or see the source tree.

mmshget is inspired by and similar to mimms, but it is smaller, easier to understand and has less features. mimms supports both seekable and live streams (mmshget supports seeakable streams only), and mimms additionally supports non-HTTP versions of the MMS protocol (mmshget supports only mmsh://, the HTTP version). mimms depends on the C library libmms, mmshget is implemented in pure Python (needs Python 2.4 later only).

2012-03-27

UTF-8 issue: find doesn't find all your files

Public bug announcement: Beware that GNU find in findutils 4.4.2 (as shipped on Ubuntu Lucid) will not find all your files if it's run in the UTF-8 locale: even if the file is there, find may just skip printing its name. Solution: If you have non-ASCII characters in your file names, use LC_CTYPE=C find instead of find.

Example:

$ echo $LC_CTYPE
en_US.UTF-8
$ ls foo*                                                    
ls: cannot access foo*: No such file or directory
$ perl -e 'die if !open F, ">", "foo\x80bar"'
$ ls foo*
foo?bar
$ find -type f
...
./foo?bar
...
$ find -name 'foo*'
$ LC_CTYPE=C find -name 'foo*'                               
./foo?bar

Possible explanation: The file name matcher won't match a file if its name cannot be parsed properly in the current locale (LC_CTYPE). That is, since foo\x80bar is not valid UTF-8, GNU find 4.4.2 will not find it.

This strange behavior can be very surprising and possibly dangerous, especially in automated shell scripts.

2012-02-18

How to make bash put the prompt to the leftmost column

This blog post explains how to configure bash so it will always put the prompt to the leftmost column of the terminal. By default, if the last command prints something without a terminating newline, the cursor remains in the middle of the line, and bash puts its prompt there.

This default behavior can be confusing for line editing, because libreadline, the library bash uses to read the next command interactively (handling cursor movements, history retrieval etc.), assumes that the prompt is put to the leftmost column, and if this assumption is wrong, libreadline may redraw the current line incorrectly. As an example, the default behavior of pressing Ctrl-A (Home) in a multiline command with a prompt not at the leftmost column would position the cursor incorrectly.

zsh fixes this by forcing each prompt to be put at the leftmost column of the terminal. The same can be achieved with bash by running this:

PROMPT_COMMAND='printf %b%${COLUMNS}b%b "\033[0;7m%\033[0m" "\r" "\e[K"'

The result looks like this (the commands typed by the user being bolded):

$ #foo
$ echo hello
hello
$ echo -n world
world$ #bar
$ PROMPT_COMMAND='printf %b%${COLUMNS}b%b "\033[0;7m%\033[0m" "\r" "\e[K"'
$ echo hello
hello
$ echo -n world
world%
$ #foo

If you like the difference, add the PROMPT_COMMAND=... assignment to your ~/.bashrc (and reopen the terminal windows) to make it permanent.

Explanations about how it works:

  • bash runs $PROMPT_COMMAND before displaying each prompt.
  • Before running $PROMPT_COMMAND, bash sets COLUMNS to the current number of columns on the terminal.
  • printf %${COLUMNS}s foo makes bash prints COLUMNS-3 spaces, and then foo, all without a newline.
  • The %b escape for bash printf is like %s, but it interprets backslash escapes, e.g. it substitutes \033 with a single character whose ASCII code is the octal 033.
  • Most modern terminals don't move to the next line if the cursor is in the rightmost column, and a single character is printed.
  • Printing an \r (carriage return) moves the cursor to the leftmost column in most terminals.
  • From the above it follows that printing COLUMNS spaces and then a \r prints some spaces and moves to the beginning of the next line, except when the cursor is already at the leftmost column, then it prints some spaces, and moves to the beginning of the current line.
  • \e[K removes everything from the cursor to the end-of-the line. It's better than a space and a \r (for removing the percent sign), because it doesn't pollute the copy-paste buffer of the terminal with extra spaces. (Thanks to Egmont for pointing this out and sending a fix!)
  • The solution does essentially this (prints COLUMNS spaces and then a \r), except that first it prints an inverted % sign, but later it hides the % sign if the cursor was in the leftmost column.

2012-01-24

Guess the programming language with array and dictionary addition

Guess the programming language.

  1. In which programming language are all of these true?
    • [] + [] is an empty string.
    • [] + {} is a string describing the empty object.
    • {} + [] is 0.
    • {} + {} is not-a-number.
  2. In which programming language are all of these true?
    • [] + [] is an empty list.
    • [] + {} raises TypeError.
    • {} + [] raises TypeError
    • {} + {} raises TypeError.
  3. In which programming language are all of these true?
    • [] + [] is an empty list.
    • [] + {} raises TypeError.
    • {} + [] raises NoMethodError
    • {} + {} raises NoMethodError.
  4. In which programming language are all of these true?
    • [] + [] is a positive number, e.g. 19806432.
    • [] + {} is a positive number, e.g. 20142304.
    • {} + [] is a positive number, e.g. 58300640.
    • {} + {} is a positive number, e.g. 27597024.

2012-01-16

How to put the window close button to the right on Ubuntu Lucid

This blog post explains how to put the the window close button to the top right corner of the window on Ubuntu Lucid, instead of the top left corner, where new Ubuntu versions tend to put it by default.

To put the window close button to the top right corner, and to arrange the other buttuns in the classic (2008 or earlier) layout, run the following command in a terminal window (without the leading $ sign):

$ gconftool-2 --type=string --set /apps/metacity/general/button_layout \
  menu:minimize,maximize,close

2012-01-08

C++ operator definitions inside and outside the class are not equivalent

This blog post presents some example code which demonstrates that having an operator outside a class is not equivalent to having it inside the class. As shown below, some implicit casts are applied only if the operator definition is outside the class.

It compiles when the operator definition is outside:

class C {
 public:
  C(unsigned a) {}
  C operator^(const C& masik) {
    return *this;
  }
 private:
  C();
};

int main() {
  C a = 5;
  unsigned b = 6;
  a ^ b;
  (C)b ^ a;
  b ^ a;  // Does not compile.
  return 0;
}

It compiles if the operator definition is outside:

class C {
 public:
  C(unsigned a) {}
 private:
  C();
};

C operator^(const C& a, const C& b) {
  return a;
}

int main() {
  C a = 5;
  unsigned b = 6;
  a ^ b;
  b ^ a;
  return 0;
}

2011-12-18

How to log out from an AppEngine app only

This blog post explains how to add a logout page to an AppEngine Python application, which will log out of the application only, without logging out of all of Google (e.g. Gmail, Calendar, Picasa, YouTube).

The default AppEngine users.create_logout_url(...) crates a logout URL which would log out from all of Google. To log out from the AppEngine app only, remove the SACSID and ACSID session cookies, which AppEngine has set right after logging in. Here is how to do it in Python:

import Cookie
import os
from google.appengine.api import users
from google.appengine.ext import webapp

class LogoutPage(webapp.RequestHandler):
  def get(self):
    target_url = self.request.referer or '/'
    if os.environ.get('SERVER_SOFTWARE', '').startswith('Development/'):
      self.redirect(users.create_logout_url(target_url))
      return

    # On the production instance, we just remove the session cookie, because
    # redirecting users.create_logout_url(...) would log out of all Google
    # (e.g. Gmail, Google Calendar).
    #
    # It seems that AppEngine is setting the ACSID cookie for http:// ,
    # and the SACSID cookie for https:// . We just unset both below.
    cookie = Cookie.SimpleCookie()
    cookie['ACSID'] = ''
    cookie['ACSID']['expires'] = -86400  # In the past, a day ago.
    self.response.headers.add_header(*cookie.output().split(': ', 1))
    cookie = Cookie.SimpleCookie()
    cookie['SACSID'] = ''
    cookie['SACSID']['expires'] = -86400
    self.response.headers.add_header(*cookie.output().split(': ', 1))
    self.redirect(target_url) 

...

application = webapp.WSGIApplication([..., ('/logout', LogoutPage), ...])
def main():
  run_wsgi_app(application)
if __name__ == '__main__':
  main()

After adding the /logout page as indicated above, offer the logout link like this:

self.response.out.write('<a href="/logout">Logout</a>')

Please note that adding a cookie which expires in the past makes the browser forget about the cookie immediately.

2011-12-11

How to turn off voicemail for Swisscom (.ch) mobiles

This blog post explains how to turn off the voicemail service (named COMBOX) provided (and enabled by default) by the Swiss mobile carrier Swisscom.

According to this PDF, lined from http://www.swisscom.ch/res/mobile/combox/index.htm, dial the following numbers:

  • ##61#
  • ##62#
  • ##67#

2011-11-18

Measure your reaction time using Python

Run this in a terminal window (without the leading $):

$ python -c 'import random, time; time.sleep(2 + 8 * random.random()); \
  print 1; t = time.time(); raw_input(); print time.time() - t'

Press Enter as soon as the number 1 appears. Your reaction time (in seconds) will be printed. For best results, don't do it over an SSH connection. If you can go below .2 second, then you are most probably not human.

2011-11-13

Announcing Portable MariaDB: Small, portable binary MariaDB distribution for Linux

Portable MariaDB is a small, portable binary distribution of the SQL server MariaDB (Monty's fork of MySQL) for Linux i386 (32-bit). Only the mysqld binary and a versatile init script are included. Portable MariaDB can be run by any user in any directory, it doesn't try to access any mysqld data or config files outside its directory. Portable MariaDB can coexist with regular mysqld (MySQL or MariaDB) and other instances of Portable MariaDB on a single machine, as long as they are not configured to listen on the same TCP port. The only dependency of Portable MariaDB is glibc 2.4 (available in Ubuntu Hardy or later).

The most up-to-date documentation of Portable MariaDB is here.

The sources are here.

Why use Portable MariaDB?

  • It's small (not bloated). Fast to dowload, fast to extract, fast to install. Quick size comparison: mariadb-5.2.9-Linux-i686.tar.gz is 144 MB, the corresponding Portable MariaDB .tbz2 is less than 6 MB.
  • It's portable: does not interfere with other MySQL server installations on the same machine.
  • It's self-contained and consistent: copy the database and the configuration in a single directory from one machine to another.

Installation

To run Portable MariaDB, you need a Linux system with glibc 2.4 (e.g. Ubuntu Hardy) or later. 32-bit and 64-bit systems are fine. For 64-bit systems you need the 32-bit compatibility libraries installed. You also need Perl.

  $ cd /tmp  # Or any other with write access.
  $ BASE=https://raw.githubusercontent.com/pts/portable-mariadb/master/release
  $ #OLD: wget -O portable-mariadb.tbz2 $BASE/portable-mariadb-5.2.9.tbz2
  $ wget -O portable-mariadb.tbz2 $BASE/portable-mariadb-5.5.46.tbz2
  $ tar xjvf portable-mariadb.tbz2
  $ chmod 700 /tmp/portable-mariadb  # For security.
  $ /tmp/portable-mariadb/mariadb_init.pl stop-set-root-password

Usage

For security, don't do anything as root.

  $ cd /tmp/portable-mariadb
  $ ./mariadb_init.pl restart
  Connect with: mysql --socket=/tmp/portable-mariadb/mysqld.sock --user=root --database=test --password
  Connect with: mysql --host=127.0.0.1 --user=root --database=test --password

Feel free to take a look at /tmp/portable-mariadb/my.cnf, make modifications, and restart mysqld so that the modifications take effect.

Security

By default, connections are accepted from localhost (Unix domain socket and TCP) only, all MySQL users are refused (except if a password has been set for root above), and root has unrestricted access. Unix permissions (such as the chmod 700 above) are protecting against data theft and manipulation on the file level.

It is strongly recommended to change the password of root to a non-empty, strong password before populating the database.

Java support

Java clients with JDBC (MySQL Connector/J) are fully supported. Please note that Java doesn't support Unix doman socket, so make sure in my.cnf that mysqld listens on a TCP port. Please make sure you have ?characterEncoding=UTF8 specified in your JDBC connection URL, otherwise some non-ASCII, non-Latin-1 characters would be converted to ?.

Unicode support

Just as with MariaDB. All encodings and collations are supported. The latin1 encoding is the default, which can be changed in my.cnf.

Language support

All natural languages (of MariaDB) are supported for error messages. Set the `language' flag in my.cnf accordingly. English is the default.

2011-11-10

How to simply compress a C++ string with LZMA

This blog post explains how to simply compress C++ with LZMA compression, using liblzma.

Use the following functions:

#include <stdlib.h>
#include "lzma.h"
#include <string>

// Level is between 0 (no compression), 9 (slow compression, small output).
std::string CompressWithLzma(const std::string& in, int level) {
  std::string result;
  result.resize(in.size() + (in.size() >> 2) + 128);
  size_t out_pos = 0;
  if (LZMA_OK != lzma_easy_buffer_encode(
      level, LZMA_CHECK_CRC32, NULL,
      reinterpret_cast<uint8_t*>(const_cast<char*>(in.data())), in.size(),
      reinterpret_cast<uint8_t*>(&result[0]), &out_pos, result.size()))
    abort();
  result.resize(out_pos);
  return result;
}

std::string DecompressWithLzma(const std::string& in) {
  static const size_t kMemLimit = 1 << 30;  // 1 GB.
  lzma_stream strm = LZMA_STREAM_INIT;
  std::string result;
  result.resize(8192);
  size_t result_used = 0;
  lzma_ret ret;
  ret = lzma_stream_decoder(&strm, kMemLimit, LZMA_CONCATENATED);
  if (ret != LZMA_OK)
    abort();
  size_t avail0 = result.size();
  strm.next_in = reinterpret_cast<const uint8_t*>(in.data());
  strm.avail_in = in.size();
  strm.next_out = reinterpret_cast<uint8_t*>(&result[0]);
  strm.avail_out = avail0;
  while (true) {
    ret = lzma_code(&strm, strm.avail_in == 0 ? LZMA_FINISH : LZMA_RUN);
    if (ret == LZMA_STREAM_END) {
      result_used += avail0 - strm.avail_out;
      if (0 != strm.avail_in)  // Guaranteed by lzma_stream_decoder().
        abort();
      result.resize(result_used);
      lzma_end(&strm);
      return result;
    }
    if (ret != LZMA_OK)
      abort();
    if (strm.avail_out == 0) {
      result_used += avail0 - strm.avail_out;
      result.resize(result.size() << 1);
      strm.next_out = reinterpret_cast<uint8_t*>(&result[0] + result_used);
      strm.avail_out = avail0 = result.size() - result_used;
    }
  }
}

Please note that in some use cases there may exist a solution which uses less memory.

See the liblzma/container. for documentation of lzma_easy_buffer_encode().

The decompression code was based on xzdec.c in xz-utils.

2011-10-27

Long standby time for Cyanogenmod 7.1 on ZTE Blade phones

This is a testimonial of the Cyanogenmod 7.1 Android spinoff operating system on the ZTE Blade phone.

I've recently installed Cyanogenmod 7.1 to my ZTE Blade. Prevously I had Cyanogenmod 7.0.3 on it, and the battery life was terrible. It didn't last more than 48 hours in standby (3G, mobile data, wifi, GPS, background synchronization switched off, only receiving a few text messages). But after installing 7.1, the battery lasted for 12 days plus 23 hours in standby mode. Awesome! Finally I have a small and cheap Android phone with long battery life.

The phone user interface also feels much snappier now, and 3D games (e.g. Falldown 3D) which lagged and were unplayable with 7.0.3 are fast and playable now.

Unfortunately I wasn't able to upgrade 7.0.3 to 7.1, but I had to wipe the phone (keeping only the SD card contents) before installing 7.1.

2011-10-18

Getting started with IntelliJ to write Android applications on Linux

This blog post gives instructions to get started with Android application development with IntelliJ on Linux.
  1. Install the Java runtime environment (JRE) and the Java compiler (in the JDK). Command to to it on Ubuntu Lucid: sudo apt-get install openjdk-6-jdk . Please note that the JRE without the JDK is not enough, IntelliJ needs the JDK.
  2. You will need about 1.5 GB of free disk space.
  3. Download IntelliJ (either the Ultimate edition or the Community edition; please note that you have to pay for the Ultimate edition after the evaluation period expires) from from. http://www.jetbrains.com/idea/download/ . I've downloaded the file from http://download.jetbrains.com/idea/ideaIU-10.5.2.tar.gz , it was about 160 MB.
  4. Download the Android SDK tools from http://developer.android.com/sdk/ . I've downloaded the file from http://dl.google.com/android/android-sdk_r13-linux_x86.tgz . It was about 160 MB.
  5. If you ever want to connect a real phone via USB, then follow the instructions http://ptspts.blogspot.com/2011/10/how-to-fix-adb-no-permissions-error-on.html do create and install the android.rules udev rule. Please also restart the udev service.
  6. Extract the downloaded archive android-sdk_r13-linux_x86.tgz .
  7. Run the android-sdk-linux_x86/tools/android tool.
  8. On the Available packages tab, find and install the following packages:
    • Android SDK Tools
    • Android SDK Platform-tools
    • Documentation for Android SDK (the latest one)
    • SDK Platform Android 2.2, API 8 (or whichever Android version you are developing for).
    • Samples for SDK API 8 (or whichever Android version you are developing for).
    • Google APIs by Google Inc., Android API 8 (or whichever Android version you are developing for).
    • Android Compatibility package
  9. In the Virtual devices tab, create a virtual device. Use these settings (make sure to enabling snapshots and disabling audio playback and recording):
  10. Start the virtual device, play with it (it's an emulated Android phone), watch how it eats your CPU capacity, and stop it by closing the emulator window.
  11. Please note that the emulator is very slow. It will happily eat 100% even if the virtual device is idle. When you disable sound playback and sound recording, it still eats about 800 MHz (tested on Intel(R) Core(TM)2 Duo CPU P9500 @ 2.53GHz).
  12. A possible bug in the Android emulator: The Launch from snapshot functionality didn't work for me in the emulator, even though the snapshot was present.
  13. In the file ~/Downloads/idea-IU-107.587/bin/idea.sh (the actual filename may depend on where you have downloaded and extracted IntelliJ to), change the line containing OPEN_JDK=$? to OPEN_JDK=1 . This will disable the startup warning.
  14. Start IntelliJ. Enter license data (or choose evaluation), accept the license agreement, just click OK in the Select VCS Integration dialog (or select a superset of the version control systems you are planning to use), unselect all Web/JavaEE plugins (they are not needed for Android development), unselect all the HTML/JavaScript plugins, in the Other plugins dialog select at least these: Android, GenerateToString, Inspection Gadgets, Intention Power Pack, JUnit, Remote Hosts Access, SpellChecker, Structural Search, Task Management, Type Migration; make sure Android is checked; finish the installation.
  15. File / New project. Create project from scratch. Next. Name: afirst. Select type: Android Module. Next. Create source... src. Next. Project JDK / Configure. /usr/lib/jvm/java-6-openjdk . OK. Next. Android SDK: ... . In the top left corner of the window, click +, and select Android SDK. Specify /home/USERNAME/Downloads/android-sdk-linux_x86 (where you have downloaded and extracted the Android SDK to). Select internal JDK: 1.6. OK. Select build target: Android 2.2 (or the Android version of your choice). OK. OK. Now you are back in the Create project wizard, with the Android SDK: selection containing Android 2.2 Platform. Finish.
  16. Wait a few minutes until the project tree afirst appears. Open afirst. Open src. Open com.example. Double click on MyActivity. The MyActivity.java source file appears.
  17. Make sure the virtual device barvirt is running in the Android emulator. Play it safe and restart the emulator.
  18. Stop adb: sudo ~/Downloads/android-sdk-linux_x86/platform-tools/adb kill-server
  19. Restart adb: sudo ~/Downloads/android-sdk-linux_x86/platform-tools/adb devices
  20. In IntelliJ Run / Edit configurations, set up devices and virtual devices like this:
  21. In IntelliJ: Run / Run. Wait a minute. The app should start on the emulator.
  22. Connect your phone with USB debugging enabled (in Settings / Applications / Development). In IntelliJ: Run / Run. Wait a minute. The app should start on the phone.

Typical IntelliJ message for starting the app on the phone:

Waiting for device.
Target device: 1234567890ABCDEF
Uploading file
 local path: /home/pts/IdeaProjects/afirst/out/production/afirst/afirst.apk
 remote path: /data/local/tmp/com.example
Installing com.example
DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/com.example"
pkg: /data/local/tmp/com.example
Success


Launching application: com.example/com.example.MyActivity.
DEVICE SHELL COMMAND: am start -n "com.example/com.example.MyActivity"
Starting: Intent { cmp=com.example/.MyActivity }

Typical IntelliJ message for starting the app on the emulator:

Waiting for device.
Target device: emulator-5554 (barvirt)
Uploading file
 local path: /home/pts/IdeaProjects/afirst/out/production/afirst/afirst.apk
 remote path: /data/local/tmp/com.example
Installing com.example
DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/com.example"
pkg: /data/local/tmp/com.example
Success


Launching application: com.example/com.example.MyActivity.
DEVICE SHELL COMMAND: am start -n "com.example/com.example.MyActivity"
Starting: Intent { cmp=com.example/.MyActivity }

2011-10-06

Named return value optimization in gcc

This blog post demonstrates that GCC 4.1 does Named return value optimization, i.e. it omits creating a temporary object in a function returning an object if all return statements in the function return the same local variable. Example code:

#include <stdio.h>

class C {
 public:
  C() { printf("+\n"); }
  ~C() { printf("-\n"); }
  C(const C&) { printf(":\n"); }
  C& operator=(const C&) { printf("=\n"); }
};

C F(int i) {
  C x;
  if (i > 1) {
    return x;
  } else {
    return x;
  }
}

C G(int i) {
  if (i > 1) {
    C x;
    return x;
  } else {
    C y;
    return y;
  }
}

int main(int argc, char**) {
  F(argc);
  printf("~~~\n");
  G(argc);
  return 0;
}

The output, as expected, even without -O... compiler optimization flags:

$ g++ test_return_object.cc && ./a.out
+
-
~~~
+
:
-
-