Dec 15, 2013

NFS server on Mac OS

  1. Edit /etc/exports: sudo vi /etc/exports Add a line like the following (presuming your home network is using the 192.168 private network. You could also use 172.17 or 10.):
    /Users -network -mask

  2. Enable nfsd: sudo nfsd enable

  3. Test your work: showmount -e

Nov 8, 2013

JIRA listener script to add assignee into Summary field

A little script to help the life better. This script is a Listener which update the summary of JIRA issue to add assignee info. I'm using JIRA Agile and its board doesn't show the assignee name so I create this script to display it in the summary field.

Code as following, save it with .groovy extension and then put it into atlassian-jira/WEB-INF/classes/com/xxx/listeners and then configure JIRA to use as class

import com.atlassian.jira.event.issue.AbstractIssueEventListener;
import com.atlassian.jira.event.issue.IssueEvent;
import org.apache.log4j.Category;
import com.atlassian.jira.event.type.EventType;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.user.util.UserManager;
import com.atlassian.jira.event.type.EventDispatchOption;
import com.atlassian.jira.component.ComponentAccessor;

class UpdateAssigneeSummaryListener extends AbstractIssueEventListener {
    Category log = Category.getInstance(UpdateAssigneeSummaryListener.class)

    void workflowEvent(IssueEvent event) {
        Issue issue = event.getIssue();
        Long eventTypeId = event.getEventTypeId();
        if ((eventTypeId.equals(EventType.ISSUE_ASSIGNED_ID) || eventTypeId.equals(EventType.ISSUE_CREATED_ID)) && issue.getResolutionDate() == null)
            def test = (issue.getSummary() =~ /^\[([A-Za-z]+)\]/)
            def summary
            def assignee = issue.getAssigneeId()
            if (test.getCount() != 0)
                // Replace the user in bracket.
                summary = (issue.getSummary() =~ /\[([A-Za-z]+)\]/).replaceFirst("[${assignee}]")
                summary = "[${assignee}] ${issue.getSummary()}"

            MutableIssue mutableIssue = (MutableIssue)issue;
            IssueManager issueManager = ComponentAccessor.getIssueManager();
            UserManager userManager = ComponentAccessor.getUserManager();
            issueManager.updateIssue(event.getUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

Oct 22, 2013

Should we move to KVM?

The virtualization wars between VMWare and KVM is not over. KVM is recently adapted by many companies such as IBM,.

Should we migrate to KVM? It's free/low cost than VMWare but show better results than VMWare...Hmmm....

Aug 19, 2013

How to fake the LSB release

On Fedora, edit the /etc/redhat-release as following

[hieult@hieuletrung ti-sdk-am335x-evm-]$ cat /etc/redhat-release
Ubuntu 10.04 release 10.04 (lucid)

Then install the lsb_release package

On Ubuntu, edit the /etc/lsb-release as following
DISTRIB_DESCRIPTION="Ubuntu lucid (development branch)"

Howto: Porting the GNU Debugger

Aug 18, 2013

Add icon to new GNOME desktop toolbar (FC16)

Alt+Right Click to add icon to Gnome toolbar in new Gnome desktop version

Debug corrupt stack


How to coerce gdb into giving a backtrace

When debugging with gdb, I sometimes encounter a problem in getting it to recognise a stack trace. Sometimes it only gives a few function calls, or none at all. Here's an example:
(gdb) bt
#0  0xb7886424 in __kernel_vsyscall ()
#1  0xb7559163 in ?? () from /lib/i686/cmov/
#2  0xb74f1387 in ?? () from /lib/i686/cmov/
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

This obviously isn't a very useful backtrace. At this point it can be useful to have a look at the registers and the contents of the stack.
(gdb) info registers
eax            0xfffffe00 -512
ecx            0x80 128
edx            0x2 2
ebx            0xb75c33a0 -1218694240
esp            0xbfe55018 0xbfe55018    <= stack pointer on x86 
ebp            0xbfe55048 0xbfe55048
esi            0x0 0
edi            0x0 0
eip            0xb7886424 0xb7886424 <__kernel_vsyscall>
eflags         0x202 [ IF ]
cs             0x73 115
ss             0x7b 123
ds             0x7b 123
es             0x7b 123
fs             0x0 0
gs             0x33 51
(gdb) x/64x $sp
0xbfe55018: 0xbfe55048 0x00000002 0x00000080 0xb7559163
0xbfe55028: 0xb75c33a0 0xb75c1ff4 0x09ec0470 0xb74f1387
0xbfe55038: 0xb77c4afd 0xb782199c 0xb782199c 0x09ec0478
0xbfe55048: 0xbfe55078 0xb77c4bf4 0x09ec0478 0xb782199c
0xbfe55058: 0x0000ffff 0xb75c3438 0xbfe55098 0xb789a240
0xbfe55068: 0x00000000 0xb782199c 0x0000ffff 0xb75c3438
0xbfe55078: 0xbfe55098 0xb7818736 0x09ec0478 0x00000000
0xbfe55088: 0xb77c50cd 0xb782199c 0xb7818709 0xb782199c
0xbfe55098: 0xbfe550b8 0xb77c54ad 0x00000000 0x00000000
0xbfe550a8: 0x0000000b 0xb75c3438 0xb77c5449 0xb782199c
0xbfe550b8: 0xbfe550c8 0xb77bb7dd 0xb782199c 0x0000000b
0xbfe550c8: 0xbfe550e8 0xb77bb84e 0x0000ffff 0xb789a240
0xbfe550d8: 0x00000000 0xb77bb830 0xb77bb839 0xb782199c
0xbfe550e8: 0xbfe55108 0xb77bc08f 0x0000000b 0x00000000
0xbfe550f8: 0x00000000 0x00000010 0xb75c1ff4 0x3efafafb
0xbfe55108: 0xbfe556c8 0xb7886400 0x0000000b 0x00000033

The values in bold are the frame pointers, forming a linked list back up the stack. If you compiled with -fomit-frame-pointer things will be harder to figure out. In this case it certainly doesn't look like the stack is corrupt. Perhaps gdb is just confused.

Pick a location slightly further up the stack and set the $sp variable, and suddenly backtrace works!
(gdb) set $sp=0xbfe55048
(gdb) bt
#0  0xb7886424 in __kernel_vsyscall ()
#1  0xb782199c in ?? () from /usr/lib/
#2  0xb7818736 in ?? () from /usr/lib/
#3  0xb77c54ad in ?? () from /usr/lib/
#4  0xb77bb7dd in SDL_QuitSubSystem () from /usr/lib/
#5  0xb77bb84e in SDL_Quit () from /usr/lib/
#6  0xb77bc08f in ?? () from /usr/lib/
#8  0xb74ede80 in ?? () from /lib/i686/cmov/
#9  0xb74efc8c in malloc () from /lib/i686/cmov/
#10 0xb7764eec in ?? () from /usr/lib/
#11 0xb7765b98 in Mix_SetPanning () from /usr/lib/
#12 0x080828b1 in I_SDL_StartSound (id=-1218694088, channel=-1218699276, 
    vol=120, sep=38) at i_sdlsound.c:671
#13 0x08073e9b in S_StartSound (origin_p=0xb624f990, sfx_id=22)
    at s_sound.c:656
#14 0x08061459 in T_MoveFloor (floor=0xb63271b8) at p_floor.c:220
#15 0x0806d0ea in P_RunThinkers () at p_tick.c:119
#16 0x0806d161 in P_Ticker () at p_tick.c:153
#17 0x08052fb6 in G_Ticker () at g_game.c:1151
#18 0x0804dbf4 in D_DoomLoop () at d_main.c:437
#19 0x0804ecc0 in D_DoomMain () at d_main.c:1506
#20 0x08054d1c in main (argc=5, argv=0xbfe55d04) at i_main.c:152


Is the art to set the sp point to correct address and then we can get a backtrace?

We need to understand the stack pointer :-)

Jun 16, 2013

Make TMP36 work on Beaglebone Black

Here is how to use the Adadfruit temperature sensor TMP36 ( on Beaglebone black for reading temperature
1) Wiring the TMP36 to BBB
Refer the following picture for TMP36 pin output

Then we need to
- Connect 1st pin to port 32 of P9 expansion slot (3.3V output)
- Connect 3rd pin to port 1 of P9 expansion slot
- Connect 2nd pin to port 39 (AIN0) of the P9 expansion slot
You can connect the 2nd pin to AIN another port, refer following image for how it is designed

2) Enable AIN on the BBB
We need to enable the AIN driver, by doing following command on the BBB console
# echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots
The above might need a kernel module BONE_CAPE or bone_iio_helper

3) Read the input
Now we can read the AIN input by cat it, for example
root@arm:~# cat /sys/devices/ocp.2/helper.14/AIN0
But the AIN0 give me some weird value, I need to use the voltage0_raw under "/sys/bus/iio/devices/iio\:device0/in_voltage0_raw";
root@arm:~# cat /sys/bus/iio/devices/iio\:device0/in_voltage0_raw
with a C application

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

//const char AIN_DEV[] = "/sys/devices/ocp.2/helper.14/AIN0";
const char AIN_DEV[] = "/sys/bus/iio/devices/iio\:device0/in_voltage0_raw";

double CtoF(double c)
  return (c * 9.0 / 5.0) + 32.0;

double temperature(char *string)
  int value = atoi(string);
  double millivolts = (value / 4096.0) * 1800;
  double temperature = (millivolts - 500.0) / 10.0;
  return temperature;

int main()
  int fd = open(AIN_DEV, O_RDONLY);

  while (1)
    char buffer[1024];
    int ret = read(fd, buffer, sizeof(buffer));
    if (ret != -1)
      buffer[ret] = '\0';
      double celsius = temperature(buffer);
      double fahrenheit = CtoF(celsius);
      printf("digital value: %s  celsius: %f  fahrenheit: %f\n", buffer, celsius, fahrenheit);
      lseek(fd, 0, 0);

  return 0;

The convert formula is as following
Step Description Example
1 Read the digital value from the ADC interface. #cat
2 Convert the digital value to millivolts.
(value / 4096) * 1800mV
(1670 / 4096) * 1800mV = 733.8867mV
3 Convert the millivolts to Celsius temperature.
(millivolts - 500mV) / 10
(733.8867mV – 500mv) / 10 = 23.38867°C
4 Convert Celsius to Fahrenheit.
(Celsius * 9.0 / 5.0) + 32.0
(23.38867°C * 9 / 5) + 32 = 74.09961°F

And here is my wiring


Jun 3, 2013

Beaglebone Black

What I bought
- Beaglebone Black
- Breadboard
- Wire
- TMP36
- MQ-3
- and a zigbee wireless sensor...