2014-03-09

How to install LFE (Lisp Flavored Erlang) on Windows


0. Install cygwin with git and make.

1. Install rebar
in cygwin do

export PATH=$PATH:/cygdrive/c/<erlang-install-dir>/bin

e.g. export PATH=$PATH:/cygdrive/c/erl5.10.4/bin


git clone git://github.com/rebar/rebar.git
cd rebar
bootstrap

this will generate rebar and rebar.cmd file.
 

2. Install LFE
in cygwn do

export PATH=$PATH:/cygdrive/c/<rebar-install-dir>
e.g. export PATH=$PATH:/cygdrive/c/erlang/rebar
 
git clone --branch develop git://github.com/rvirding/lfe.git
cd lfe
vi Makefile  ## change makefile to use rebar.cmd instead of rebar
%s/rebar /rebar.cmd /g
:wq
 
make

erl -pa /somewhere/lfe/ebin -noshell -s lfe_shell start

Instead of using "erl -pa ..." option, you can copy the whole lfe directory under the <erlang-install-dir>/lib
and use "erl -noshell -s lfe_shell start".


example:

$ pwd
/cygdrive/c/lfe
$ ls
bin  ebin   Emakefile  include  Makefile         rebar.config  test
doc  emacs  examples   LICENSE  README.markdown  src           VERSION
$ erl -pa ebin -noshell -s lfe_shell start
LFE Shell V5.10.4 (abort with ^G)
> (+ 1 2 )
3
> (: lists reverse '(3 2 1))
(1 2 3)
> (halt)
$
 
 
lfeshell.bat
set path=%path%;c:\erl5.10.4\bin
erl -pa ebin -noshell -s lfe_shell start
 
Starting GUI lfe shell
werl -pa \path\to\lfe\ebin
1> lfe_shell:server(). 
 
 
Ref.
https://github.com/rvirding/lfe/wiki/Get-started
https://github.com/rvirding/lfe/blob/develop/doc/lfe_shell.txt 
http://stackoverflow.com/questions/4698591/lisp-flavored-erlang-on-windows
http://stackoverflow.com/questions/2835942/how-do-i-install-lfe-on-ubuntu-karmic 

2012-08-27

Tagging UniVerse Basic in ctags

Use etags in Exuberant Ctags, instead of the one in emacs.

find -H /somewhere/UVBasic/src -name '*.[BHu]' \
 | xargs -I{} ctags -e -a -o TAGS-uvb --langdef=uvbasic --langmap=uvbasic:.B.H.u \
--regex-uvbasic='/^([^ \t]+):$/\1/' --regex-uvbasic='/^[ \t]*PROGRAM[ \t]+([^ ]+)$/\1/i'  \
--regex-uvbasic='/^[ \t]*(FUNCTION|DEFFUN)[ \t]+([^ ]+\))/\2/i'  \
--regex-uvbasic='/^[ \t]*(EQUATE|EQU)[ \t]+([^ ]+)[ \t]+TO[ \]+/\2/i' {}

2011-09-14

constructing process tree from the ps -ef result

#! /usr/bin/awk -f

# Usage:
# ps -ef | ./proctree.awk
# ps -f > proclist.txt; ./proctree.awk proclist.txt

BEGIN { pid_col = 2; ppid_col = 3 }

# find the field number for PID and PPID column
/PID +PPID/ {
for (i=1; i < NF; i++) {
if ($i == "PID") {
pid_col = i ; ppid_col = i + 1
print; break
}
}
next
}

{
processes[$pid_col] = $0
children[$ppid_col] = children[$ppid_col] "," $pid_col
if ($ppid_col == 0 || $ppid_col == 1) child_of_swapper_init = child_of_swapper_init "," $pid_col
}

END {
if (0 in processes) {
print processes[0]
split(substr(children[0], 2), child_of_swapper, ",")
for (pid in child_of_swapper) {
if (pid != 1) print processes[pid]
}
}

if (1 in processes) {
print_tree(1, 0)
} else {
## find the top processes.
for (pid in children) {
if (pid in processes) continue
origins = origins "," pid
}

split(substr(origins, 2), top_procs, ",")
for (pid in top_procs) {
print_tree(top_procs[pid], 0)
}
}
}

function print_tree(pid, depth, myfmt, mypid, mychld)
{
if (index(child_of_swapper_init, pid)) depth = 0

if (depth == 0) {
if (pid in processes) {
print processes[pid]
} else {
depth = -1
}
} else {
myfmt = sprintf("%%%is%%s", 3 * depth)
printf(myfmt "\n", " ", processes[pid])
}

split(substr(children[pid], 2), mychld, ",")
for (mypid in mychld) {
print_tree(mychld[mypid], depth + 1)
}
}

#__end__

2011-09-05

How to generate cyclic numbers in ksh

Sometimes, I need to generate limited number of temporary files in loop like below.

while :
do
ps -elf > /tmp/ps.log.$cyclic_number_here
done


Generating cyclic number is an easy job. For example, next function does that.

#! /usr/bin/ksh
GEN_CYCLIC_CALL_COUNT=1
gen_cyclic_number()
{
typeset -i max=$1 mod

((max < 1)) && print 0 && return

((mod = GEN_CYCLIC_CALL_COUNT % max))
if ((mod == 0)); then
((GEN_CYCLIC_CALL_COUNT = max + 1))
print -- $max
else
((GEN_CYCLIC_CALL_COUNT += 1))
print -- $mod
fi
}
But this function will not output the correct numbers when used in command subsititution because it's executed in a subshell.

Correct and easier way is to use proper arithmetic expressions as arithmetic expansion is done in the shell, not in a subshell.

typeset -i i=-1
while :
do
ps -elf > /tmp/ps.log.$((i = (i += 1) % 3)) # generates ps.log.0, ps.log.1, ps.log.2
done


What you need is just 0 and 1, even simpler solution is here.
typeset -i i=1
while :
do
ps -elf > /tmp/ps.log.$((i ^= 1))
done

2011-06-27

Could not access remote file "/usr/local/bin/sstep" in software item

* Problem
In installing depot file using swinstall command in HP-UX, it can fail with next error even though all the installation is done in localhost.

ERROR: Could not access remote file "/usr/local/bin/sstep" in
software item
"tusc.tusc-RUN,r=8.0,a=HP-UX_B.11.31_64,v=:/usr/local" due to
an internal error on the remote system.
ERROR: Failed installing fileset "tusc.tusc-RUN,r=8.0". Check the
above output for details.
* Retry number 1 of 1 for loading files for fileset
"tusc.tusc-RUN,r=8.0".
* Installing fileset "tusc.tusc-RUN,r=8.0" (1 of 1).
ERROR: Could not access remote file "/usr/local/bin/sstep" in
software item
"tusc.tusc-RUN,r=8.0,a=HP-UX_B.11.31_64,v=:/usr/local" due to
an internal error on the remote system.
ERROR: Failed installing fileset "tusc.tusc-RUN,r=8.0". Check the
above output for details.

* Solution
Check if your /etc/hosts file has error, correct it if so.

For example, if your hosts file is like below

127.0.0.1 loopback localhost myhostname
10.10.10.1 myhostname

Change it to

127.0.0.1 loopback localhost
10.10.10.1 myhostname

Then restart the swagentd using "swagentd -r" command.

And run the swinstall again.
For example; swinstall -s $PWD/tusc-8.0-ia64-11.31.depot \*

2010-12-17

Running X window through SSH tunnel

* Prerequisite
The secure shell daemon (sshd) in the Unix box should be set up to support X11 forwarding, to enable this
1. Login as root
2. Edit /etc/ssh/sshd_config adding next line
X11Forwarding yes
(In HP-UX, sshd_config is in /opt/ssh/etc/)
3. Restart sshd
in AIX: /etc/rc.d/rc2.d/Ssshd {stop|start} OR stopsrc -s sshd; startsrc -s sshd
in Linux: /etc/init.d/sshd {stop|start}
in Solaris: svcadm refresh ssh
in HP-UX: /sbin/init.d/secsh {stop|start}


* Case 1: my PC with cygwin directly connects to remote Unix box (my PC <----> Unix)

1. Start cygwin XWin Server using Windows menu or using startxwin command in cygwin command window.

2. Set up secure shell tunnel by running next command in a cygwin command window.
cygwin$ ssh -X -Y -C user@remote_unix_host

3. In the shell session opened in above step, make sure DISPLAY environment variable is set and run X comands like xterm, xclock, ...

Sample session:

cygwin_in_WinXP$ ssh -X -Y -C johndoe@debian
johndoe@debian's password: XXX
johndoe@debian ~$ echo $DISPLAY
localhost:11.0

johndoe@debian ~$ xterm &
[1] 1234
johndoe@debian ~$

xterm should pop up in my Windows XP box.


* Case 2: my PC with cygwin cannot connect to the remote Unix box as it's behind firewall having private IP address 192.nnn.nnn.nnn. (my PC <----> SSH relay host <----> Unix)

Let's call ssh relay host ssh_box and target Unix host xwin_box.

0. Add next lines in your Windows hosts file (C:\Windows\System32\drivers\etc\hosts).
127.0.0.1 locahost xwin_box
10.10.1.10 ssh_box # public IP address, so no problem for direct connection

Also make sure xwin_box is registered in the /etc/hosts file of ssh_box too.
(In fact, aliasing xwin_box is optional as localhost can be used in step 3 below)

1. Start cygwin XWin Server using Windows menu or using startxwin command in cygwin command window.

2. Set up secure shell tunnel by running next command in a cygwin command window.
cygwin$ ssh -C -L 2222:xwin_box:22 user@ssh_box

3. Run next command in another cygwin command window.
cygwin$ ssh -X -Y -C -p 2222 xuser@xwin_box
or
cygwin$ ssh -X -Y -p 2222 xuser@localhost

4. In the shell session opened in above step 3, make sure DISPLAY environment variable is set and run X comands like xterm, xclock, ...

2010-04-05

read timeout in ksh

Timing out read in Korn shell

It is possible to time out the read command using coroutines.
We need a helper script, let's call it timout_read.sh, and main script with read command.

1. timeout_read.sh
#! /usr/bin/ksh

typeset -i timeout_after_this=$1
sleep $timeout_after_this

kill -0 $PPID 2>/dev/null && kill -USR1 $PPID
#ps -p $PPID >/dev/null && kill -USR1 $PPID 2>/dev/null

2. main.sh

#! /usr/bin/ksh

myvar=.yes ## default value.
timeout=${1:-4}

read_myvar()
{
trap return USR1
timeout_read.sh $1 &
read myvar?"Your value for myvar: "
trap "" USR1
}

## do something

read_myvar $timeout
if [[ $myvar = .yes ]]; then
# do default action
echo Read timed out. myvar = $myvar
else
# do proper action depending on user input
echo You entered $myvar
fi
* read in bash has -t option for this functionality.