A bit about

Hello, everyone! All you can see below is just my bank of information. Some material I've found in the fathomless net, some I've learned myself. Don't think all of the information here is right or actual, but may be it could be of use for you :) All feedback is welcome, especially constructive ones :)

Wednesday, August 27, 2008

Adding SubVersion to the Init (Linux)

First of all, I tried this solution on Debian 4.0r1. But in fact I don't think there will a huge difference between distributives.

As I could realize from packages came with two my distributives (ASP Linux v10 and Debian 4.0r1) - SubVersion provides svnserve which can be started in the current terminal or loaded as a daemon (also there is a possibility to run in inetd mode, but I used daemon mode). But installer doesn't add svnserve to init among with other daemons. So I had to do this myself.

We have several directories:

  • /etc/init.d - storage for all scripts which are called during change of runlevel. These scripts must accept one argument that can be start, stop, reload, restart and force-reload

  • /etc/rc*.d - symbolic links to the corresponding scripts in init.d directory. All of them a called when entering corresponding runlevel.

I've added the next script called "svn" into init.d:
#!/bin/sh

#standard logging functions
. /lib/lsb/init-functions

case "$1" in
start)
log_begin_msg "Starting SubVersion...";
if ! svnserve -d -r "/repositories"; then
log_end_msg 1
exit 1
else
log_end_msg 0
fi
;;
stop)
log_begin_msg "Stopping SubVersion...";
if ! pkill svnserve; then
log_end_msg 1
exit 1
else
log_end_msg 0
fi
;;
reload|restart|force-reload)
log_begin_msg "Stopping SubVersion...";
if ! pkill svnserve; then
log_end_msg 1
else
log_end_msg 0
fi

log_begin_msg "Starting SubVersion...";
if ! svnserve -d -r "/repositories"; then
log_end_msg 1
exit 1
else
log_end_msg 0
fi
;;
*)
echo "Usage: /etc/init.d/svn {start|stop|reload|restart|force-reload}"
exit 1
;;
esac

exit 0

Then I've just created link in /etc/rc2.d directory:
# ln -s /etc/init.d/svn /etc/rc2.d/S22svn

And that's all. Subversion is automatically started on runlevel 2 and is stopped during shutdown or going down to runlevel 1.

Monday, August 18, 2008

Colored output to a vt100 (e.g. Linux console)

Lots of Linux programs use colors to paint their output (ls, for example). But there're no special commands to do the same thing yourself. Solution was found here: http://www.freeos.com/guides/lsst/misc.htm (BTW, quite good tutorial). These are control characters of Linux console. For instance, if you print \033[31m, all your next output will be red. The list of codes of all supported colors can be easily obtained by experiment or found in Google, but just to save time here it is:
\033[22;30m - black
\033[22;31m - red
\033[22;32m - green
\033[22;33m - brown
\033[22;34m - blue
\033[22;35m - magenta
\033[22;36m - cyan
\033[22;37m - gray
\033[01;30m - dark gray
\033[01;31m - light red
\033[01;32m - light green
\033[01;33m - yellow
\033[01;34m - light blue
\033[01;35m - light magenta
\033[01;36m - light cyan
\033[01;37m - white
\033[01;0m - default scheme


Also, there're a lot of other control characters (some of them can controls leds on a keyboard).

All these knowledge was needed for me to write a script that prints Linux-style log (it was just for fun :)). Two functions - first shows a log message with required number of separating symbols (dots, for example), and the second prints colored result of operation. Here is my product:
# function does color output of the result. OK if $1 equal 1, and FAILED otherwise
function echo_result()
{
if [ $1 -eq 0 ]; then
echo -e "[\033[31mFAILED\033[0m]";
else
echo -e "[\033[32m OK \033[0m]";
fi
}

# function outputs the string given in the first parameter and adds required number of dots
function echo_log()
{
str="$1";
len=`expr length "$str"`; # obtain length of the given string and correct this value by 1 for the next loop
len=$((len+1));
for i in `seq $len 34`; do
str="${str}.";
done
echo -n "$str";
}

# Usage
RES=1;
echo_log "Log message 1";
cmd1 && \
cmd2 && \
cmd3 || RES=0;
echo_result $RES;

RES=1;
echo_log "Log message 2";
cmd1 && \
cmd2 && \
cmd3 || RES=0;
echo_result $RES;


As the result we could see:
Log message 1.....................[ OK ]
Log message 2.....................[FAILED]

Saturday, July 19, 2008

Guest access to a Samba server

Just a little note: I had a problem with guest access to samba server (he always asked username and password, while there were public folders with all permissions). The root of the problem was in the following line in /etc/samba/smb.conf:

security = user

To have a guest account enabled change this line to:

security = share

P.S. Stolen from opennet.ru :)

Win cmd: copy only required extension

Let's imagine we have a directory structure with photos (jpg) and videos. Now we have to extract only photos, but save directory structure (photo albums). The following cmd command could be useful:

> xcopy /E /I /Y Albums\*.jpg OnlyPhotos

This will create directory OnlyPhotos which is copy of Albums, but contains only *.jpg files.

RegEx: Alternative lazy operator

If we, for example, want to get the first directory name by means of regular expressions, we probably will use lazy operator "*?" to find all symbols before the first entry of '/':
t2/dir1/file1.txt
t2/dir1/file2.txt
t2/test.txt
t2/new.txt

^.*?/

But for unknown reasons, sed doesn't know what is lazy operator and cuts all symbols until the last '/'. So, in this case we can use the following alternative:
$ find t2 -type f | sed -r "s#^[^/]*##"
/dir1/file1.txt
/dir1/file2.txt
/test.txt
/new.txt

This expression will search for any number of symbols before the first '/' (this might be any other symbol. So, instead of:

.*?<MY_SUMBOL>

we can use

[^<MY_SUMBOL>]*

Tuesday, July 8, 2008

VBA: How to extract unique values from cells range

Sometimes it's very useful to obtain all unique values from column, for example, into array. The first way is to look through all the cells in range and copy their values to an array, checking existence. Another way is to add each value to a special VBA object called Collection. As I understood from an example, this object will raise exception if next value already exists in the collection (and the script will handle this exception and continue). This method leaves existence checking to VBA.
But there's the third way - leave all of the work to Excel's filter. The algorithm is:

  1. Find enough empty place in the worksheet

  2. Apply advanced filter (which will copy unique value to the given range)

  3. Copy all values to an array

  4. Clear copied values and cells formatting

So, let's assume we have the following table
 ABCD
11a  
22b  
31c  
43c  
53d  

And we want to find all unique values for column A. Also, we have empty place next to the table. In this case we can use the follwing VBA code:

Dim ColA_Values() As Integer
' select the required range and apply filter
Range("A1:A5").Select
Selection.AdvancedFilter Action:=xlFilterCopy, CopyToRange:=[D1], Unique:=True

' obtain number of unique values (number of rows in column D)
Dim LastRow As Long
LastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, "D").End(xlUp).Row

' copy values to the array
ReDim ColA_Values(LastRow)
Dim i As Integer
For i = 1 To LastRow
ColA_Values(i) = ActiveSheet.Cells(i, "D").Value
Next

' clear temporary values and formatting
Range("D1:D" + CStr(LastRow)).Select
Selection.Clear

Monday, July 7, 2008

VBA: Number of rows in a column and vice versa

Found this trick here and modified a bit. These two functions can be used to determine number of cells in a particular column or a row of an Excel data sheet.

Function ColsInRow(Row) As Long
ColsInRow = ActiveSheet.Cells(Row, ActiveSheet.Columns.Count).End(xlToLeft).Column
End Function

Function RowsInCol(Col) As Long
RowsInCol = ActiveSheet.Cells(ActiveSheet.Rows.Count, Col).End(xlUp).Row
End Function

Monday, May 12, 2008

lastword function in GNU Make

If you saw the previous post, you would notice that for MAKEFILE_LIST variable it's better to use lastword function (because this variable could contain more then one file name, but we need the last one). The problem is that some versions of GNU Make don't support this function. Another way to obtain the same result can be found here.
$(word $(words text),text)

instead of
$(lastword text)

Longer, but it works.

Tuesday, April 29, 2008

How to know makefile name and targets

In lots of cases I had to know the name of the current makefile and targets, Make was called with. I expected that solution of these problems should be in special variables, however I couldn't find such variables even in GNU Make reference.

Why do I need to know such information on runtime? So, lets start with name of the current makefile.

MAKEFILE_LIST - list of the currently used makefiles

Imagine that we have to do recursive call of Make to call different targets, with different variables. For example, I have a number of targets with the same actions, but with different paths. And I want to have one target that do these actions and another targets which call the first one with different MY_PATH values. In common case, the code will be:
all: t1 t2

t1:
$(MAKE) MY_PATH=~/component1 build
t2:
$(MAKE) MY_PATH=~/component2 build
build:
$(CC) -o $(MY_PATH)/binary source.c

It's working. But our makefile could be called other than "makefile". My solution is predefined variable MAKEFILE_LIST. It contains the list of makefiles used for build.
all: t1 t2

t1:
$(MAKE) -f $(MAKEFILE_LIST) MY_PATH=~/component1 build
t2:
$(MAKE) -f $(MAKEFILE_LIST) MY_PATH=~/component2 build
build:
$(CC) -o $(MY_PATH)/binary source.c

I've tested this code in different versions of Linux, MacOS and even under Cygwin. May be I'll find another, simpler way for recursive call, but at this moment I have only this one.

MAKECMDGOALS - list of the specified targets

Sometimes it happens, that different targets require different set of variables, defined by user. For instance, make src should export a repository tree to the current directory (prepare sources to build) and thus require a repository address and a revision. Also, make build should build these sources. May it require ARCH variable, which means target architecture. So, it's normal to check variables existence, but it's nonsense to make a user define architecture while exporting repository tree ;) That's why we should check only those variable, which are required by the selected target.
I found predefined variable MAKECMDGOALS investigating output of command $(warning $(.VARIABLES)) (see the GNU Make reference). In the end, let's try to write a little make, illustrating usage of this variable:
ALL=src build

ifeq ($(MAKECMDGOALS),)
MAKECMDGOALS=$(ALL)
endif

ifneq ($(filter $(MAKECMDGOALS), src),)
ifeq ($(REV),)
$(error REV variable should be defined)
endif
ifeq ($(SVN),)
$(error SVN variable should be defined)
endif
endif
ifneq ($(filter $(MAKECMDGOALS), build),)
ifeq ($(ARCH),)
$(error ARCH variable should be defined)
endif
endif

all: $(ALL)

src:
svn export -r $(REV) $(SVN)

build:
gcc -march=$(ARCH) test.c -o test


UPD: I missed this page, because thought that it's not the variable I need: http://www.gnu.org/software/automake/manual/make/MAKEFILE_005fLIST-Variable.html

Sunday, April 27, 2008

HTTP query from PHP

Here is a simple PHP script, which sends http request and reads output of the server. First of all it uses HTTP header to read amount of incoming data. But if there's no Content-Length field, the script reads until EOF.

<?
// just kind of query to Google's image search
$Artist = "Evanescence";
$Album = "Fallen";

$query = rawurlencode("\"".$Artist."\" \"".$Album."\" Cover");
// encode part of url (query string)
$query = "/images?gbv=2&hl=ru&newwindow=1&q=".$query;
// add HTTP request syntax
$query = "GET ".$query." HTTP/1.1\r\n\r\n";

// open socket
$google_sock = fsockopen(gethostbyname("images.google.ru") ,80, $errno, $errstr, 30);
if(!$google_sock)
die("Couldn't connect to images.google.com");

// send the query
fputs($google_sock, $query);

$html = ""; // clear html code
$html_length = 0; // length of html
$header_line = ""; // line of HTTP header
do
{
// get next line of HTTP header
fscanf($google_sock, "%[^\n]", $header_line);
// remove symbols like \r
$header_line = trim($header_line);

$header_name = trim(strtok($header_line, ":"));
if($header_name == "Content-Length")
$html_length = strtok(":");
}
while($header_line != "");

if($html_length > 0)
$html = fread($google_sock, $html_length);
else
{
while( !feof($google_sock) )
$html .= fread($google_sock, 4096);
}

fclose($google_sock);

echo $html;
?>

Tuesday, April 22, 2008

Vim syntax highlighting

In most configurations, by default, Vim highlights language or file specific syntax (if not, try using :syntax on. But it uses file's name or its extension to determine required syntax configuration. It's very comfortable, but in some cases we have to give a name to a file, which doesn't correspond contents of the file. Therefore, Vim can't correctly determine configuration. To do it manually one can use :set filetype=<...>

The list of available syntax highlightings can be found in /usr/share/vim/vim63/syntax, just look through file names.

Thursday, April 17, 2008

SVN and EOL style

Sometimes it happens that we should checkout or export file from repository with different End-Of-Line styles (0x0D 0x0A for Windows, 0x0A for Unix and 0x0D for MacOS). SVN let's you choose this style on checkout or export. All you need is to set property svn:eol-style=native and then point out required EOL in command line:

> svn export --native-eol CRLF <...> # For Windows
$ svn co --native-eol LF <...> # For Linux
$ svn export --native-eol CR <...> # For MacOS

Monday, April 14, 2008

BASH parameter parsing

I always tried to parse parameters, which were fed to my shell script by means of while loop. But when I was writing me next labwork, I noticed that my lecturer always use for loop. So I tried to compare speed of these two methods. I wrote the following two sctipts, which just iterate through parameter set:

test1.sh

#!/bin/bash
for i in $*; do
a=0; #just to do something
done;


test2.sh

#!/bin/bash
while [ "$1" != "" ]; do
shift;
a=0; # just to prevent time difference in this action during comparison
done


After that, I fed 1000 arguments to both scripts and run time tool:

$ time ./test1.sh `seq 1 1000`

real 0m0.177s
user 0m0.162s
sys 0m0.016s
$ time ./test2.sh `seq 1 1000`

real 0m0.304s
user 0m0.266s
sys 0m0.037s


Difference is amazing! But I thought that comparison "$1" = "" in the second script, would take much time, so I wrote the third variant of script:

#!/bin/bash
while [ $# -gt 0 ]; do
shift;
a=0;
done


run:

$ time ./test3.sh `seq 1 1000`

real 0m0.343s
user 0m0.316s
sys 0m0.026s


Look at this! In case of big number of arguments, it could take more time for shell to count them than just compare strings.

Resume: Ok, it's great and the first my thought was "forget about while loop for parameter parsing and use for", but... But I used to check the next parameter while parsing arguments which show a type of the next parameter (./test1.sh -o output_file). In this case it seems to be hard to use for. So my opinion is - keep in mind that shift operator is expensive, but kind of loop depends on current situation. K.I.S.S.! Don't make you code unreadable just to speed up it on ~0.1s :)

UPD:
Example with for doesn't allow us to feed arguments with spaces (like ./test1.sh "a b" or ./test1.sh a\ b)

Tuesday, April 8, 2008

Update: Unremovable spaces by means of CSS

This is an update for this post. I used white-space: pre to tell browser not to remove sequences of spaces. But while posting previous subject, I found that this option has a very big minus: text becomes "unwrapable" and is clipped by borders of the nearest html table. After looking through many sites I found a new option (which became available recently) - white-space: pre-wrap. It assumes that all spaces are indissoluble, but browser can wrap text on these spaces.

Monday, April 7, 2008

Make with N jobs

It's widely known that GNU Make can run with several jobs. User just have to pass -j key to Make command line. For example:

$ make -j 4 all

But lets write two very simple Makefiles and try recursive call of Make. Let's imagine we have src directory, and two source files - foo1.c and foo2.c in this directory. The first Makefile will be located in this src folder:

C=gcc
LINK=gcc
RM=rm -rf

BIN=foo
OBJ=foo1.o foo2.o

all: clean $(BIN)

$(BIN): $(OBJ)
$(LINK) $(OBJ) -o $@

$(OBJ): %.o : %.c
$(C) $^ -o $@

clean:
$(RM) $(BIN) $(OBJ)


Ok, this will give us binary file from sources. Now go to the parent folder and write the second Makefile:

all:
(cd src; make)


And that's all! Call Make from the parent directory and it will enter directory src and run another make there. But what if we set number of jobs?

$ make -j 2
make[1]: Entering directory '<...>/src'
make[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.


Google says that Make passes additional information about jobserver on recursive call. But it does so only if he know that the child program is another Make. In our case he doesn't know. But let's do little change in the second Makefile:

all:
(cd src; $(MAKE))


Try running make with -j 2 again? Everything is Ok :) Because $(MAKE) is a special variable, which says that the child process is Make.

Friday, April 4, 2008

Magic The Gathering, deck

Yes! I received a deck of MTG cards at the beginning of this week. It's an Elvish one. It could be very powerful with Elf tokens. All in all, it's a very interesting game, I think. I don't wanna spend a lot of money for this, it's just for fun :)

Monday, March 31, 2008

My move to a new e-mail

It seems so simple - to register a new address and to tell it to your friends. But don't forget that in some point of view, your mailbox is something like your home when using the Web. Especially, on such services as Google or Yandex, where you have a lot of features, assigned to your mail account.
First of all, I’ve tried to find function like “Rename my mailbox”. I thought that if I can change, for example, my username in Windows or Linux, why can’t I just rename my mailbox? I was so naive! )) May be I missed something, but I haven’t found any information in Google’s help or among my friends how to do this simple step.
So, the only way for me was creating a new account and copying all information from the old one. And it took for me equally two hours. Special Thank for my ISP for stable connect during this hard time )) Below are the common steps, which I have done.

The first evident step – register a new account
There was no problem, my target mailbox’s name wasn’t occupied by anyone. By the way, it’s very convenient to work in two different browsers – the new account in Firefox and the old one in IE.

2. Forget about previous account – use forwarding
For my Google accounts, I saw the 2 ways – make the old mailbox forward all incoming mail to the new one; or allow POP and IMAP access for the old mailbox and make the new mailbox check out updates from there. I preferred the second way. Why? GMail automatically puts a label for all mail, coming from the old mailbox. A have already configured debugger129 account (I downloaded incoming mail to my phone and iPod), so I had to do just simple activity – go to settings of my new mailbox switch to “Accounts” tab, find “Get mail from other accounts” and type login and password for debugger129. Done! The next morning I had all my old mail with label “debugger129” in maxim.kukushkin mailbox.

3. Tell your friends
I felt as spammer when sending absolutely equal mails to all my contacts )) Why didn’t I just copy all email addresses to the “To” field and send only one message? Because everyone could see the list of other recipients. I don’t want to share my contact list with everyone, therefore I had to send copies. But before I could send mails, I imported the contact list from the old mailbox. GMail->Contacts->Export->Google’s CSV format, and then download the file. New GMail->Contacts->Import->Browse, and upload the previously downloaded file. All OK! All contacts are here now.

4. Change your contact information on most websites
While searching through my contacts, trying to find human mailboxes, I came across a lot of addresses which belong to diary.ru, vkontakte.ru, etc. It was helpful for me. I remembered that I have an accounts on these websites and vkontakte, for instance, uses my mailbox as login. I went to all of them immediately and updated my contact information.

5. Update your contact information in messengers and at work
I remembered that I had entered e-mail information in a one of registration forms at work.

6. Google Blogger
First of all, I had to create a Blogger account for my new mailbox. It’s simple, I just entered (or copied) the same information as it was in previous account. Next step – login to Blogger with debugger129 account and invite maxim.kukushkin to authors. Accept invitation. Return to Blogger and set admin privileges for the new author (maxim.kukushkin). Delete debugger129 from admins and authors. That’s all! My blog now belongs to the new account.

7. Google Reader
It took very little time. Just the same trick with Import/Export as it was for GMail contacts :)

8. iGoogle
I remembered that I have a lot of gadgets in iGoogle, and I want most of them to appear within my new account. I realized that I don’t use games which were in my previous iGoogle, and I didn’t waste time for searching for the games. Also, it wasn’t hard to find the required gadgets by searching for the by their title. The final touch – add theme. I haven’t found any gothic theme, so I decided on times of day, which I’ve seen on my friend’s iGoogle. Done!

9. Account information
Then I noticed “My Account” title in the right upper corner of the iGoogle and remembered to copy some information from previous account.

10. Google Notebook
I haven’t found any ways to Import/Export all notes. I think, this feature is under development process inside Google, because almost all other Google’s services have this one. Ok… Copy/Paste/Copy/Paste… awful!...

I think that’s all, because I haven’t touched other services yet :) Oh! Nearly forgot, at this moment I’m trying to find good transport for my new Jabber account and thinking about setting up my own transport on my own server. Just an idea…

P.S. While investigating Blogger’s settings, found that it provides OpenID. I have an OpenID now, welcome, Web2.0 )))

Wednesday, March 26, 2008

Google Flight Simulator

Update your Google Earth application and press Ctrl-Alt-A when it's loaded. You'll enter Google Flight Simluator, which is based on Google Earth. It provides you simple airplane control. Of course, picture isn't very good, but nevertheless it's very interesting to fly over Moscow for example :) By the way, if you try to land outside a runway, you'll crash ))) Three types of input devices are supported - keyboard, mouse and joystick. Keyboard seems to be very hard for controlling, mouse is simpler, but I enjoyed flying by means of joystick (similar to Sega). Here are some screenshots:

One of Moscow airports, I don't know which one

Landing... ))

Unremovable spaces by means of CSS

As I started posting here I faced the challenge - when I write program code it's necessary to paste spaces actually before each line. Also, I decided to use <code> tag to separate program code. By default, all sequences of spaces are replaced by one and to copy-paste a lot of &nsbs; is very inconveniently. So I found resolution in CSS:

.post code{
white-space: pre;
}


".post" is local class which is used for all posts; "pre" means that spaces shouldn't be deleted (like <pre>). Other possible values are "normal" and "nowrap".

Song of the day

Within Temptation - Deceiver of Fools. This song repeated in my mind the whole day :) And now, I'm listening it through my iPod and really enjoy Sharon's voice and music of the band. Here are the lyrics:

{He feeds on fear
He feeds on pain
He rules again
With growing hate
He will gain
Their faith again

No light in the darkness
Is too small to see
There's always a sparkle of hope
If you just believe...}

He told the tale so many times
About the dream not meant to be
In a world of the free

{Plays with your mind}

As faith for the future faded fast
He grows strong with their displeasure
It sets him free

(chorus)
Deceiver of hearts
Deceiver of fools
He rules with fear
Deceiver of hopes
Deceiver of fools
He rules again

He feeds on fear
Poisons the truth
To gain their faith
To lead the way
To a world of decay

{Rules your heart}

He'll sell your soul to the grave
Without a hesitation to make
He belongs to the dark

(chorus)

Please awake
And see the truth
He can only be
If you believe what he tells you
Remember who you are
What you stand for
And there will always be a way

(chorus)

In my heart there is a place
In my heart there is a trace
Of a small fire burning
A sheltering ray shines through this night
Although it's small, it's bright
But darkness is lurking

He will sell your soul to bitterness and cold
Oh fear him

Deceiver of hearts
Deceiver of fools
He rules with fear
Deceiver of hopes
Deceiver of fools
Shall he rule again?

Tuesday, March 25, 2008

Continue of loop in VBA

As I understood from this post, there's no special instruction to skip loop iteration in VBA. So, may be the only way to do it is to place a special label just before the end of the current loop and then use GoTo statement:

For i = 1 To 10
If i = 5 Then
GoTo nextiteration
End If
' do some more stuff
nextiteration:
Next

File existance checking in VBA

I found this method in the Internet, in two different forums. Just write a simple function-wrapper:

Function Fileexists(fname) As Boolean
If Dir(fname) <> "" Then
Fileexists = True
Else
Fileexists = False
End If
End Function


Then you can use this function just the same way as in many other languages.

Monday, March 24, 2008

Clearing the Clipboard in VBA

There is no special function to clear Clipboard, so we should use Win API functions. The following code clears the Clipboard:

' System functions
Public Declare Function OpenClipboard Lib "user32" (ByVal hWnd As Long) As Long
Public Declare Function EmptyClipboard Lib "user32" () As Long
Public Declare Function CloseClipboard Lib "user32" () As Long

' Implementation of function which clears the Clipboard
Public Function ClipboardEmpty() As Boolean
Dim l As Long, i As Long
l = OpenClipboard(0&)
If l <> 0 Then
l = EmptyClipboard()
i = CloseClipboard()
End If
ClipboardEmpty = (l <> 0)
End Function

' Using the function
If Not ClipboardEmpty() Then MsgBox("Clipboard isn't empty")



This way you can prevent Excel messages like "There is a large amount of information on the Clipboard..." when closing a window (be means of VBA)