18 November 2006

perl: интересное описание perl6 в журнале у avva

Описание возможностей perl6 в плане расширения синтаксиса языка
опубликовал LJ пользователь avva.

perl: как посмотреть содержимое переменной

Для того, чтоб легко посмотреть содержимое переменной в perl -- в частности, HASH и ARRAY (LIST)
можно использовать модуль Dumper


use Data::Dumper;
.
.
.
print Dumper $variable;

14 November 2006

erlang: Using namespaces and packages in Erlang

It's possible to use separate namespaces for different applications in erlang,
thus converting modules from app_module1, app_module2 and etc to
app.module1, app.module2 names. Modules in package can call each other by using shorter name, i.e. module1:func() and module2:func1().


For complete article see:
http://www.erlang.se/publications/packages.html

22 September 2006

Erlang: String processing optimiziation

I wish to share an experience which I had today when writing code.

I had a following function, which splits binary on enter character. I used it to split binaries to separate lines.

Original code looked like this -- which is obvious dumb solution for
that task.


break_on_nl(B) -> break_on_nl(B, []).
break_on_nl(<<"\n", Tail/binary>>, Res) -> {lists:reverse(Res), Tail};
break_on_nl(<<>>, Res) -> {lists:reverse(Res), <<>>};
break_on_nl(<<C, Tail/binary>>, Res) -> break_on_nl(Tail, [C|Res]).


I.e. just cutting one character a time, checking that we reached \n and returning collected string and remaining tail if we reached it.

After some occasional loon on this code I realized, that I can greatly improve it. Instead rebuilding binary to list and then reversing list I could just check every byte of binary, check if it is an Enter char, and then return binary splitted to 2 parts.

Code like that:


break_on_nl1(B) -> break_on_nl1(0, B).
break_on_nl1(Len, Bin) when Len == size(Bin) ->
{Bin, <<>>};
break_on_nl1(Len, Bin) ->
<<Msg:Len/binary, Symb, Tail/binary>> = Bin,
case Symb of
$\n -> {Msg, Tail};
_ -> break_on_nl1(Len+1, Bin)
end.


Main advantage is that I do not modify original binary and it passed
from one call to next one without copying.

This little code rewrite gave me 2 times speed increase, which was quite essential, because I have strong timing constrains for that code.

18 September 2006

Как обойти модель безопасности JavaScript

Довольно часто возникает задача -- подгружать данные динамически. В случае, если источник данных находится на том же домейне, что и загруженный скрипт, то модель безопастности бразуера позволит обратится к нему при помоэи XmlHttpRequest (если совпадают протокол, доменное имя и порт в URL с которого загружен JavaScript и с которого запраиваются данные).

В противном случае возможно загрусить данные с удаленного сайта, только создав динамически таг <script> и указав все данные запроса в URL, в виде GET запроса.
Код который загрузится с удаленного сайта должен вызвать какую-либо функцию JavaScript, что бы сообщить об успешной загрузке данных.

Такой подход реализован в библиотеке Subsys_JsHttpRequest.

А упрощенный вариант реализован в SimpleXMLRPC -- библиотеке, которая реализует несколько разных типов запросов (XMLRPC, получение JSON-кодированных данных при помощи POST запроса и получение данных при помощи включения .js файла с удаленного сервера).

Вот что делает код библиотеки --

span = document.createElement("SPAN");
span.id = "__jsload__" + id;
span.style.display = 'none';
span.innerHTML = 'Text for stupid IE.' +
'';
s = span.getElementsByTagName("script")[0];
s.language = "JavaScript";
document.body.appendChild(span);
setTimeout(function() { if (s.setAttribute) s.setAttribute('src', href); else s.src = href; }, 10);


Т.е. создается span, в нем таг script, a потом в качестве src у скрипта ставится URL. После добавления скрипта в DOM дерево при помощи appendChild начинается скачивание JS скрипта.

После того, как он был скачан -- можно либо обращаться к его переменным и функциям, так как js файл полностью импортируется в область видимости(scope) загружающе программы --
при условии, что загруженный файл имел в себе правильный JS код, либо -- как это делает SimpleXMLRPC -- JS файл состоит из строчки типа
XMLRPC.dataReceived(id, ActualData);
, которая и дает знать вызывающему скрипту, что данные уже загружены.

PS. нужно быть внимательным и удалять старые, ненужные объекты <script>

Author: Gaspar Chilingarov
Keywords: javascript, ajax, web 2.0, xmlrpc, json-rpc, simplexmlrpc

14 September 2006

Firefox2: google search

Firefox2 have very pleasant feature to show Google Suggest, when you typing search terms in Searchbox at topmost-right corner. Nice.


Author: Gaspar Chilingarov

Erlang to Vim: first alpha-version patches

Erlang to Vim integration



Now you can try a first alpha-version of patches for vim, which turn Vim into C-node for erlang. Thus you can easily send rpc calls from vim to erlang and get results in vim script. This will provide ability to use distel in vim too, not only in emacs, allowing faster development and more comfortable IDE for erlang programmers.

Please see vim erlang integration page for more instructions.

Keywords: Vim, Erlang, integration, vim scripts, erlang ide

Author: Gaspar Chilingarov

08 September 2006

Erlang programming: Converting numbers to strings

You can see - how to convert numbers to textual representatoin, using erlang/yaws as a backend.
Module to process english is about 100 lines of code.

Here it is:

 
number(N) ->
lists:foldl(
fun
(El, []) -> El;
([], List) -> List;
(El, List) -> List ++ " " ++ El
end,
[], to_number(N)).

to_number(N) when is_list(N) ->
try
to_number(list_to_integer(N), 0)
catch
error:_ -> ["Error converting to text. Please enter integer."]
end;
to_number(N) when is_list(N) -> to_number(list_to_integer(N), 0);
to_number(N) when is_integer(N) -> to_number(N, 0).

to_number({0}, _Order) -> [];
to_number({N}, Order) -> to_number(N, Order);

to_number(0, N) when N>0 ->
[];

to_number(0, 0) -> ["zero"];
to_number(1, _Order) -> ["one"];
to_number(2, _Order) -> ["two"];
to_number(3, _Order) -> ["three"];
to_number(4, _Order) -> ["four"];
to_number(5, _Order) -> ["five"];
to_number(6, _Order) -> ["six"];
to_number(7, _Order) -> ["seven"];
to_number(8, _Order) -> ["eight"];
to_number(9, _Order) -> ["nine"];
to_number(10, _Order) -> ["ten"];
to_number(11, _Order) -> ["eleven"];
to_number(12, _Order) -> ["twelve"];
to_number(20, _Order) -> ["twenty"];
to_number(30, _Order) -> ["thirty"];
to_number(40, _Order) -> ["forty"];
to_number(50, _Order) -> ["fifty"];
to_number(60, _Order) -> ["sixty"];
to_number(70, _Order) -> ["seventy"];
to_number(80, _Order) -> ["eighty"];
to_number(90, _Order) -> ["ninety"];
to_number(N, _Order) when N < 20 ->
[composite(N-10) ++ "teen"];
to_number(N, Order) when N < 100 ->
[ to_number({r(N, 10)}, Order), to_number({m(N, 10)}, Order) ];
to_number(N, Order) when N < 1000 ->
[ to_number({d(N, 100)}, Order), "hundred" | to_number({m(N, 100)}, Order) ];
to_number(N, 0) when is_integer(N) ->
N1 = m(N, 1000),
to_number(
d(N, 1000),
1,
to_number({N1}, 0)
).

to_number(_N, Order, Result) when Order > 11 -> Result;
to_number(0, _Order, Result) -> Result;
to_number(N, Order, Result) ->
Mod = m(N, 1000),
to_number(d(N, 1000),
Order+1,
to_number(Mod, Order) ++ [ order(Order, m(N, 1000)) ] ++ Result).

composite(3) -> "thir"; % for numbers in range 13-19
composite(4) -> "four";
composite(5) -> "fif";
composite(6) -> "six";
composite(7) -> "seven";
composite(8) -> "eight";
composite(9) -> "nine".

order(_, 0) -> "";
order(O, N) -> order(O);
order(O, Number) ->
"order = (" ++ integer_to_list(O) ++ ")".

order(1) -> "thousand"; % 10 3
order(2) -> "million"; % 10 6
order(3) -> "billion"; % 10 9
order(4) -> "trillion"; % 10 12
order(5) -> "quadrillion"; % 10 15
order(6) -> "quintillion"; % 10 18
order(7) -> "sextillion"; % 10 21
order(8) -> "septillion"; % 10 24
order(9) -> "octillion"; % 10 27
order(10) -> "nonillion"; % 10 30
order(11) -> "decillion". % 10 33

d(N, Mod) -> N div Mod.
r(N, Mod) -> (N div Mod)*Mod.
m(N, Mod) -> N rem Mod.

07 September 2006

Инструкция по установке поддержки армянского языка в X Window System

Инструкция по установке поддержки армянского языка в X Window System

Инструкция по настройке FreeBSD системы для отображения и ввода армянских текстов

Отображение армянских текстов:

Если у Вас система дистибутив X Windows -- XFree86 версии 4.0 и выше, то как у Вас есть как минимум несколько UNICODE .BDF фонтов (из семейства -misc-fixed-*), которые содержат в себе символы армянского алфавита. Если у Вас система X Windows -- Xorg, то в ней тоже есть фонты поддерживающие армянский. Вам просто нужно выбрать их в текстовом редакторе или браузере для отображения армянского текста.


Набор армянских текстов:

1. Необходимо открыть терминал (с системой X Windows распространяется терминал xterm).
2. Необходимо получить привелегии суперпользователя -- root.
Для этого нужно набрать в терминале

##
su -
##
В ответ на запрос команды su введите пароль суперпользователя. Если команда su сразу пишет "su: Sorry", это значит, что вы не входите в группу wheel и не имеете право получать привелегии суперпользователя. Тогда вам придется войти в систему пользователем root.

3. Необходимо проверить, что в системе присутствуют файлы
##
/usr/X11R6/lib/X11/xkb/symbols/am
/usr/X11R6/lib/X11/xkb/symbols/pc/am
##

Если их нет, но их можно скачать ««здесь»». Первый файл нужно скопировать в /usr/X11R6/lib/X11/xkb/symbols/am, второй в /usr/X11R6/lib/X11/xkb/symbols/pc/am, и выполнить команды
##
chmod 644 /usr/X11R6/lib/X11/xkb/symbols/am
chmod 644 /usr/X11R6/lib/X11/xkb/symbols/pc/am
chown root:wheel /usr/X11R6/lib/X11/xkb/symbols/am
chown root:wheel /usr/X11R6/lib/X11/xkb/symbols/pc/am
##

Если такие файлы уже есть на вашей системе, стоит выполнить команду
##
grep phonetic /usr/X11R6/lib/X11/xkb/symbols/am \
/usr/X11R6/lib/X11/xkb/symbols/pc/am
##

Если у Вас уже есть фонетическая армянская раскладка -- то Вы увидете следуещее:
##
/usr/X11R6/lib/X11/xkb/symbols/am:xkb_symbols "phonetic" {
/usr/X11R6/lib/X11/xkb/symbols/pc/am:xkb_symbols "phonetic" {
##

Если команда grep ничего не вывела, то Вам стоит скачать файлы раскладок с этого сайта и скопировать на место существующих у Вас.

В старых файлах армянской раскладки была только typewriter раскладка.


4. Необходимо изменить конфигурацию системы X Window, чтоб включить поддержку армянского.

Необходимо открыть в любом редакторе файл /etc/X11/XF86Config .

Найдите следующий текст

##
Section "ServerLayout"
Identifier "XFree86 Configured"
Screen 0 "Screen0" 0 0
InputDevice "Mouse0" "CorePointer"
InputDevice "Keyboard0" "CoreKeyboard"
EndSection
##

Выделенный жирным текст -- это название Вашей секции описания клавиатуры. Найдите секцию, где Identifier такое-же значение

Она должна выглядеть приблизительно так:
##
Section "InputDevice"
Identifier "Keyboard0"
Driver "keyboard"
Option "XkbModel" "pc105"
Option "AutoRepeat" "250 30"
EndSection
##

Вам необходимо добавить несколько строк, чтоб она выглядела следующим образом:
##
Section "InputDevice"
Identifier "Keyboard0"
Driver "keyboard"
Option "XkbModel" "pc105"
Option "AutoRepeat" "250 30"

Option "XkbLayout" "us,am(phonetic)"
Option "XkbVariant" "winkeys"
Option "XkbOptions" "grp:alt_shift_toggle,grp_led:scroll"
EndSection
##


Строчки XkbLayout описывают что используются 2 раскладки -- английская и армянская фонетическая. Если Вы пользуетесь typewriter раскладкой, то Вам нужно убрать (phonetic), что бы получилось
##
Option "XkbLayout" "us,am"
##


XkbVariant указывает,что разрешены дополнительные клавиши (левая/правая Win и Menu).

XkbOptions указывает, что для переключения между раскладками будет использоваться - Alt+Shift. При использовании армянской раскладки на клавиатуре будет гореть индикатор ScrollLock.
Правый Alt+Shift и кнопка Menu будут переключать раскладки по циклу us -> am, а левый Alt+Shift будет переключать в последовательности - am -> us и если у вас X.org, то не будет переключаться с раскладки us на am.

Далее вам необходимо сохранить изменения и перезагрузить X Server.




Инструкция по настройке Linux систем для отображения и ввода армянских текстов

Если вы используете современные системы (скажем, Fedora Core 4), то по умолчанию система уже поддерживает отображение армянского алфавита.
Для настройки ввода армянского текста, если Вы используете оболочку GNOME, достаточно щелкнуть на панели правой кнопкой, выбрать "Add to panel", выбрать из списка апплетов "Keyboard indicator" и нажать OK. После того, как апплет добавится на панель, необходимо правой кнопкой мыши щелкнуть на нем, выбрать пункт меню "Preferences", после чего добавить из списка возможных раскладок армянскую раскладку.

Если Linux система не поддерживает добавления новых раскладок через графический интерфейс, то Вам придется выполнить те-же шаги, что и для FreeBSD, с той разницей, что указанные файлы могут ханодится в других местах.


Keywords: armenian unicode layout, x11, freebsd, linux, writing in armenian, armenian font
Author: Gaspar Chilingarov
Copyright 2005

DNS: инсталляция DJB DNS (tinydns) на CentOS

VPS (Virtual Private Server) от vpsland идет по умолчанию с установленным bind. A bind, как известно, это не только проблемы с безопастностью, это и безбожно отжираемая память, которой на VPS хостинге и так мало. Поэтому пришлось снести bind и поставить djbdns (tinydns).

Для уставноки скопируйте этот скрипт к себе на сервер, сделайте файл со скриптом выполняемым (chmod 755 имя_файла), и запустите его.

#!/bin/sh
#Create the following directories:
mkdir -p /usr/local/djb/build
mkdir -p /usr/local/djb/patches

# Download and extract the three patches:
# //get the patches:
cd /usr/local/djb/patches
#//Download the following (small download, still ... be kind to his bandwidth .. :) ):
wget http://www.thedjbway.org/patches/djb_errno_patches.tgz
#//Extract:
tar -xzvf djb*.tgz
#//Several .patch files should output

#Download and extract the three packages:

#//Change directories and download the main packages:
cd /usr/local/djb/build
wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz
wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz

#Extract and patch each of the three packages:
#(you should still be in the /usr/local/djb/build directory for all three of the following)

#Extract and Patch ucspi:

cd /usr/local/djb/build

#//ucspi
gunzip ucspi-tcp-0.88.tar
tar -xf ucspi-tcp-0.88.tar
cd ucspi-tcp-0.88
patch -p1 < ../../patches/ucspi-tcp-0.88.errno.patch
#//[output from patch...]
patch -p1 < ../../patches/ucspi-tcp-0.88.a_record.patch
#//[output from patch...]
patch -p1 < ../../patches/ucspi-tcp-0.88.nobase.patch
#//[output from patch...]
make setup check
./install
./instcheck

#Extract and Patch daemontools:

cd /usr/local/djb/build

#//daemontools
gunzip daemontools-0.76.tar
tar -xpf daemontools-0.76.tar
rm daemontools-0.76.tar
cd admin/daemontools-0.76
patch -p1 < ../../../patches/daemontools-0.76.errno.patch
#//[output from patch...]
package/install


# Extract and Patch djbdns:

cd /usr/local/djb/build

#//djbdns
gunzip djbdns-1.05.tar
tar -xf djbdns-1.05.tar
cd djbdns-1.05
patch -p1 < ../../patches/djbdns-1.05.errno.patch
#//[output from patch...]
make
make setup check
./install
./instcheck

#Next, you'll add the necessary user accounts and use the tinydns-conf script to create an installation based on the IP of your box:
#xx.xx.xx.xx represents the IP address represented with the output of "ifconfig" on your box.

echo "Input your ip address, (ifconfig output follows)"
ifconfig
read IP

#//create the group and users -- modify if needed
groupadd -g 91 dns
useradd -g 91 -u 91 -d /nonexistent -c "tinydns" -s /sbin/nologin Gtinydns
useradd -g 91 -u 92 -d /nonexistent -c "tinydns" -s /sbin/nolodin Gdnslog

#//here the tinydns-conf script copies files and creates the useable IP-based installation
cd /usr/local/bin
tinydns-conf Gtinydns Gdnslog /etc/tinydns $IP

#Once that's done, you'll set a symbolic link to the svcscan application to keep tinydns running if crashed:

#//create the symbolic link of djbdns under the symbolic link of the svcscan application
cd /
mkdir /service
ln -s /etc/tinydns /service
#//force us to be patient and wait for the service to start
sleep 5
#//check to make sure the service is running
svstat /service/tinydns
#//should return something like "/service/tinydns: up (pid 24957) 4870 seconds"



Ключевые слова: dns, djb dns, tinydns, системное администрирование, исталляция, unix, CentOS, Debian
Автор: Гаспар Чилингаров (Gaspar Chilingarov)

DNS: installing DJB DNS (tinydns) on fresh CentOS

Setup tinydns on CentOS or Debian



As a user of vpsland.com I've got a VPS with CentOS (which have packaging structure very simular to Debian) with bind installed.
This is not the best solution - because bind in both insecure and uses too much memory.

Here it is a small script to install tinyDNS to the VPS server.

Cut it here, paste into some file on your server, make that file executable (chmod 755 filename) and run it.


#!/bin/sh
#Create the following directories:
mkdir -p /usr/local/djb/build
mkdir -p /usr/local/djb/patches

# Download and extract the three patches:
# //get the patches:
cd /usr/local/djb/patches
#//Download the following (small download, still ... be kind to his bandwidth .. :) ):
wget http://www.thedjbway.org/patches/djb_errno_patches.tgz
#//Extract:
tar -xzvf djb*.tgz
#//Several .patch files should output

#Download and extract the three packages:

#//Change directories and download the main packages:
cd /usr/local/djb/build
wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz
wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
wget http://cr.yp.to/djbdns/djbdns-1.05.tar.gz

#Extract and patch each of the three packages:
#(you should still be in the /usr/local/djb/build directory for all three of the following)

#Extract and Patch ucspi:

cd /usr/local/djb/build

#//ucspi
gunzip ucspi-tcp-0.88.tar
tar -xf ucspi-tcp-0.88.tar
cd ucspi-tcp-0.88
patch -p1 < ../../patches/ucspi-tcp-0.88.errno.patch
#//[output from patch...]
patch -p1 < ../../patches/ucspi-tcp-0.88.a_record.patch
#//[output from patch...]
patch -p1 < ../../patches/ucspi-tcp-0.88.nobase.patch
#//[output from patch...]
make setup check
./install
./instcheck

#Extract and Patch daemontools:

cd /usr/local/djb/build

#//daemontools
gunzip daemontools-0.76.tar
tar -xpf daemontools-0.76.tar
rm daemontools-0.76.tar
cd admin/daemontools-0.76
patch -p1 < ../../../patches/daemontools-0.76.errno.patch
#//[output from patch...]
package/install


# Extract and Patch djbdns:

cd /usr/local/djb/build

#//djbdns
gunzip djbdns-1.05.tar
tar -xf djbdns-1.05.tar
cd djbdns-1.05
patch -p1 < ../../patches/djbdns-1.05.errno.patch
#//[output from patch...]
make
make setup check
./install
./instcheck

#Next, you'll add the necessary user accounts and use the tinydns-conf script to create an installation based on the IP of your box:
#xx.xx.xx.xx represents the IP address represented with the output of "ifconfig" on your box.

echo "Input your ip address, (ifconfig output follows)"
ifconfig
read IP

#//create the group and users -- modify if needed
groupadd -g 91 dns
useradd -g 91 -u 91 -d /nonexistent -c "tinydns" -s /sbin/nologin Gtinydns
useradd -g 91 -u 92 -d /nonexistent -c "tinydns" -s /sbin/nolodin Gdnslog

#//here the tinydns-conf script copies files and creates the useable IP-based installation
cd /usr/local/bin
tinydns-conf Gtinydns Gdnslog /etc/tinydns $IP

#Once that's done, you'll set a symbolic link to the svcscan application to keep tinydns running if crashed:

#//create the symbolic link of djbdns under the symbolic link of the svcscan application
cd /
mkdir /service
ln -s /etc/tinydns /service
#//force us to be patient and wait for the service to start
sleep 5
#//check to make sure the service is running
svstat /service/tinydns
#//should return something like "/service/tinydns: up (pid 24957) 4870 seconds"



These instructions were taken from http://www.interworx.com/forums/archive/index.php/t-967.html forum.

Keywords: dns, djb dns, cent os, tinydns, daemontools, svstat, setting up dns, system administration
Author: Gaspar Chilingarov