Thursday, July 28, 2005

Ctrl-XCtrl-V

Well i just bumped into this article (http://www.chiark.greenend.org.uk/~sgtatham/bash-notify/)
searching for aynchronous jobs.
As my brain is a non starter i dont understand some terms like asynchronous.
So now to keep things simple i feel an asynchronous job is a background job as it can end anytime :).

According to the article "set -b" and "set +b" both of them have issues.
set -b will just corrupt your display and "set +b" can create lot of jobs.Dont ask me why :).
But the feature of Ctrl-XCtrl-V prints the bash version etc and then restores the command line on new line "as it was".

$ps ax
GNU bash, version 3.00.16(1)-release (i686-pc-linux-gnu)
$ps ax

The author had even written a patch for this ..Will have a look at it sometime :).

hash builtin - 2

Okay i am back to the hash builtin again.Lets trace phash_flush in hashcmd.c.
As expected it calls hash_flush.A look at the top of the function shows what it does,removes and discards
all entries in TABLE.If FREE_DATA is non-null then its kind of a destructor else call free() to free up the memory.

First it is checked if (table == 0) or if number of entries in the table are zero.

Once we are sure that number of hash entries are not zero, we iterate through the hash tables buckets.
Typically we call free(item->data),free(item->key) and free(item).

And finally we set the initial bucket pointer to NULL and set the number of entries to zero.

This is quite staightforward ,the way it should be.
So as we are doing okay ,lets move to the other functions.
Lets see phash_remove now,this as expected calls hash_remove.
A peek inside the code shows we try to get the bucket for the string first.
This buckets is got by hashing the string and anding with number of buckets -1 :).
The string typically is 'ls','ps' etc no mention of the data here but then who cares when its is getting deleted.
No.The pointer is being returned after being deleted from the list so lets go back to phash_remove.
Well i went back to phash_remove and tried to print the data before it gets freed.No luck.
I am reading junk so where is the path stored??
Okay i screwed up again ,without reading i assumed the complete file path would be stored as item->data but
thats not the case.item->data is a pointer to a struct PATH_DATA which contains the path.

Didnt i tell you my brain is a goner anyway back to code and let me print the pathname just before it gets freed,
(Dead Man Walking style) :).

Bingo.. now i get to print /usr/bin/ls just before its cleaned up by "hash -d ls" :).

Wednesday, July 27, 2005

hash builtin

I think my brain will finally be a non starter.Anyhow here are my thoughts on the hash builtin of bash.

So i browsed haslib.h where HASH_TABLE is defined as

typedef struct hash_table {
BUCKET_CONTENTS **bucket_array; /* Where the data is kept. */
int nbuckets; /* How many buckets does this table have. */
int nentries; /* How many entries does this table have. */
}

Obviously the next question would be what is BUCKET_CONTENTS,remember a hash has buckets..
Well not quite..:) anyways as we have the source with us lets go there ..:)

typedef struct bucket_contents {
struct bucket_contents *next; /* Link to next hashed key in this bucket. */
char *key; /* What we look up. */
PTR_T data; /* What we really want. */
unsigned int khash; /* What key hashes to */
int times_found; /* Number of times this item has been found. */
} BUCKET_CONTENTS;

As we can see hash_table has bucket_array,number of buckets and number of entries.
I have feeling the number of buckets may increase as we need more...
As we look into BUCKET_CONTENTS has a pointer to the next bucket,
a key ( like 'ls'),data (/usr/bin/ls),khash ( i think this is the hashed value),
times_found ( lol..source is enough i guess :) ).

Now lets look at the functions in hashcmd.c

phash_create
phash_freedata
phash_flush
phash_insert
phash_insert
phash_search

phash_create
This in turn calls hash_create (hashlib.c) with appropriate number of buckets (FILENAME_HASH_BUCKETS=64)

phash_search
Probably this is what is interesting,this in turn ccalls hash_search.

bucket= HASH_BUCKET(string,table,hv)

this in turns calls hash_string,the real hashing function.

for (i = 0; *s; s++)
{
i *= 16777619;
i ^= *s;
}

The comment says magic is in the interesting relationship between the special prime 16777619 and 2^32 and 2^8.
As fas as i can tell,2^8 is *s and i is 2^32 :).

HASH_BUCKET ands the value of string with the number of buckets.
I am just thinking of collisions but i guess each bucketjust starts up a link list.

spawnve

There was this patch on the bash mailing about making bash run faster on cygwin.

It was pointed out that there were issues with signal handling after the patch is applied.
After the function in the patch is called SIGINT handler is getting lost making the shell to exit instead of just cancelling the current line.

A quick look at the patch shows the following code.

+ sigdelset(&child_sig_mask, SIGTSTP);
+ sigdelset(&child_sig_mask, SIGTTIN);
+ sigdelset(&child_sig_mask, SIGTTOU);

Job control signals are removed from the child_sig_mask,so does that mean they will not be blocked?
In any case the mask was set to top_level_mask instead of child_sig_mask in the following line and was pointed out.

+ sigprocmask (SIG_SETMASK, &top_level_mask, &old_sig_mask);

Friday, July 22, 2005

Quoting during command substitution

I was corrected in #bash channel in irc by trash regarding this.

During variable assignment,its better to quote the rhs.

For example

$myvar="hello world"


but this isnt needed if you are doing something like

$myvar="$(echo hello world)"



As this is equivalent to
$myvar=$(echo hello world)


Thursday, July 14, 2005

A small thing about vi regex

Well i was trying to remove all the spaces in the lines that are present before text.

So i thought to use vi's command mode and run


:%s/^\s+//


But this doesnt work ,then i found out (http://www.geocities.com/volontir/) that in vi the way to specify the '+' quantifier is to use,
'\+'.So it turns out the way to do it is .

:%s/^\s\+//



Also '?' quantifier is '\='.

Monday, July 11, 2005

PROMPT_COMMAND

Its an interesting bash variable..bash whenever it finishes a command or null command would try to run this..

$ PROMPT_COMMAND=date
Mon Jul 11 18:46:42 IST 2005
$
Mon Jul 11 18:46:42 IST 2005
$
Mon Jul 11 18:46:43 IST 2005
$
Mon Jul 11 18:46:43 IST 2005
$ uname
Linux
Mon Jul 11 18:47:23 IST 2005


I guess it will be more fun to set it to "clear" :).

completion for directories starting with '='

Initially i thought this could be a bug but later realised that this behavior is because of readline treating '=' as a word break character.

# mkdir =foo =foobar
# cd =\=foo
-bash: cd: ==foo: No such file or directory


Basically when you hit TAB after types just '=' , bash adds "\=foo".
What is treated as a word break character can be modified by changing the value of COMP_WORDBREAKS(Thanks to Chet :) ).

$ echo $COMP_WORDBREAKS
"'@><=;|&(:
$ COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}
$ echo $COMP_WORDBREAKS
"'@><;|&(:

Also you just saw bash's search and replace functionality.If there is no "slash" in the end ,the pattern is deleted from the variable :).

Wednesday, July 06, 2005

filename expansion after parameter expansion

This point came up during an intersting post on bug-bash.I just ran a few commands to check this out.

If nullgob is set then bash will not echo the pattern if it fails the filename expansion.

$echo abc*
abc*
$shopt -s nullglob
$echo abc*

$

So now if you have a variable like

$test=p*
$echo $test
purchase
$echo "$test"
*



Moral of the story:Quoting (double) a variable suppresses filename expansion.

Sunday, July 03, 2005

Three arrows


$ cat <<< Yothere
Yothere

cat <<< "$(< for.sh)"
#for(( i=1;i<6;i++))
for i in $(ls)
do
echo $i
done


I can call it extended here document .So as you can see this allows for variable subsitution as well. :)