Something I wish I had time to do

Write a conversational IRC bot, lol.

I Figure, load two processes, a communications layer and an automation layer; in this case the communications layer would be a simple relay between an IRC channel and the automatas standard I/O streams; messages on the channel would get written to the automatas standard input, and messages to send to the channel would be read from the automatas standard output.

I would want the thing to have some concept of learning, maybe build a dictionary of language; perhaps start off with a limited knowledge of words; storing words it doesn’t know into a database for later analysis. And then once a number of words have been manually entered into it with attached meta data, program it to perform the analysis itself; trying to figure out what kind of words it sees but doesn’t know about yet, and then write out plugin code with the bots “best guess”, and if it gets it wrong, I could manually change it, and it would have to study the differences between my correction and it’s choice, and modify it’s guessing based on experience. (Implementing that would be fun in it’s own right, lol.).

That would logically be easy enough to design and study, the question is how to make it educating enough that you can actually have people chatter with it.

Haha, I always laugh when people mistake bots for humans on IRC xD

What I hate about programming

Some months ago when it reached Kris Moore’s attention (late as usual) that I had brought up security issues with his Firefox3 PBI, he changed it to something almost as bad. A couple weeks ago, I heard back from Kris that he had [naively] changed the code for making Fx3 the users default browser would no longer run as “root”. After a little more conversation he split it off to something better.

Originally it was a part of the script that runs during PBI installation (and worse then the below script), probably tired of my replies he made an extra wrapper around the Firefox3, that asks the user if they want Firefox3 set default or not, rather then workin’ the user database at install time. (I refuse comment on the following scripts predecessors: if you want to know more, read his SVN). The solution he came up for that wrapper, was to invokes the following code as the user when necessary:

#!/bin/sh
# Helper script to make FF the default browser for a user
##############################################################################

# Get the users homedir
USER="`whoami`"
HOMEDIR="`cat /etc/passwd | grep ^${USER}: | cut -d ":" -f 6`"

if [ -e "${HOMEDIR}/.kde4" ]
then
KDEDIR=".kde4"
else
KDEDIR=".kde"
fi

if [ ! -e "${HOMEDIR}/${KDEDIR}/share/config/kdeglobals" ]
then
echo "ERROR: No kdeglobals file for $USER"
exit 1
fi


TMPKFILE="${HOMEDIR}/.kdeglobals.$$"
TMPKFILE2="${HOMEDIR}/.kdeglobals2.$$"
rm ${TMPKFILE} >/dev/null 2>/dev/null

cat ${HOMEDIR}/${KDEDIR}/share/config/kdeglobals | grep -v '^BrowserApplication' > ${TMPKFILE}

rm ${TMPKFILE2} >/dev/null 2>/dev/null
touch ${TMPKFILE2}
while read line
do
if [ "$line" = "[General]" ]
then
echo "$line" >> ${TMPKFILE2}
if [ "${KDEDIR}" = ".kde4" ]
then
echo "BrowserApplication[$e]=!/Programs/bin/firefox3" >> ${TMPKFILE2}
else
echo "BrowserApplication=!/Programs/bin/firefox3" >> ${TMPKFILE2}
fi
else
echo "$line" >> ${TMPKFILE2}
fi
done < ${TMPKFILE}

# all finished, now move it back over kdeglobals
rm ${TMPKFILE}
mv ${TMPKFILE2} ${HOME}/${KDEDIR}/share/config/kdeglobals

exit 0

which is more secure then the original implementation, and more efficient also. Tonight I sent Kris a casual (read: adapt to need, don’t take as is) suggestion from yours truly:

#!/bin/sh
# Helper script to make FF the default browser for a user
# Should work for KDE3 and KDE4.
##############################################################################

PROG="!/Programs/bin/firefox3"
FILE="./share/config/kdeglobals"

for D in "${HOME}/.kde" "${HOME}/.kde4"
do
cd $D 2>/dev/null || break;

if [ ! -e "$FILE" ]
then
echo "ERROR: No kdeglobals file, unable to set $PROG as default"
exit 1
fi

ed -s "$FILE" <<EOF
/[General]/
/BrowserApplication.*=/
s/=.*/=${PROG}/
wq
EOF
# write your own error handlers
done

exit 0

which should work as far as I can test; since I lack a working KDE install (compiling KDE4.2+ is on my todo list). It’s not perfect, but it sure is nicer then what he had a few months back. I included the a diff of the two scripts in my last message, which may very well go against my decision to “never” send these people patches. But I really don’t care if he accepts it or not, because while I believe in being helpful, I also I do not like doing peoples jobs for them.

I’m a lazy good for nothing creep, but I am lazy of muscle – not lazy of mind. The most productive code I have ever written, is the code I was smart enough /not/ to write in the first place.

merging the new code into master

After 3~4 days of coding, I’ve just merged the parserlexer branch back into master; I love coding 🙂

 commit 9857e5e9556f31543075fb4a74350dbda97a42e5
Merge: c9a8ae4... bb425eb...
Author: Terry ....snip...
Date: Wed Apr 8 07:23:19 2009 +0000

Merge branch 'parserlexer'

The new parser, lexer, and quote expansion code (+ a few bugfixes) has
finally been merged into the mainline of development (branch 'master').
This marks the new sh_eval(), tpsh_parse(), expand_quotes, tpsh_lex()
functions in such a way that they should be considered 'stable' for
general usage.

some nice things that come with this:

a sane way of quoting stuff; but not sh compatible (”’ = ‘, not an error), more then one set of quotes on the line; and things like `cd /foo; vi bar` finally work xD. In the course of the necessary bug smashin’ for the merge, I’ve also cleaned out a few pains in the todo file, that have been there since last month++ lol.

things that remain to be done: pluggable completion; make completion play nicer with perl/gnu readline backends; restore support for pipes (critical); handling of keybinding (likely painful across perl/gnu/zoid Term::ReadLine backends; but at least zoid is nice…). In the more long term: control flow, (subshells), better `handling`, {anonymous macro/grouping}, more advanced I/O redirections (i.e. only >, >>, and < currently work lol); making `fc -l` and `history list` use a format for display rather then print(); make &do_getopt able to be configured by callers (so fc can accept negative indexes, etc); give a way to turn off shell options (set - and set + currently turn on, only lol); and who knows what else that I can't remember atm.
and to abuse {erls idea of objects and verbs: eval { $spidey sleep $now };

I wonder if a programmer goes to heaven, does GOD let him study HIS assembly language?

tpsh: test of expand_quotes()

$ echo 'hi bye' foo "$USER" and "~" or ~
expand_quotes ': echo | hi bye | foo "$USER" and "~" or ~
expand_quotes ": foo | $USER | and "~" or ~
expand_quotes ": and | ~ | or ~
hi bye foo $USER and ~ or /usr/home/Terry
$

# note:
# the 2 spaces /displayed/ between hi and bye are a bug in
# tpsh; echo'ing things to file via I/O redirection works
# properly. "$USER" is not expanded because expand_parameters()
# still needs adjustments.
#

tpsh_parse invokes expand_quotes() to break up its input line based on the shells quoting rules; and proceeds to go about it’s business. tpsh_lex() then accepts the token buffer and begins building a new data structure from it. The tokens from tpsh_parse get analyzed and reassembled “on the quotes”, i.e. it will do it’s check on ‘hi ‘ and ‘bye’ and the rest as separate elements; then reassemble the argument vectors as an array reference: becoming ‘hi bye’ again. (id est quote expansions add escapes to tell the lex phase where to rejoin things) After everything is said and done between parse and lex, the queue like data structure is ready, the argument vectors contained there in are ready to be mapped onto resolve_cmd() calls for execution.

To hunt down any other booboos in the expand_quotes() subroutine, I’ve made it display it’s work, so I can see how it detects what when testing the shell. basically as “expand_quotes QUOTE: unquoted | quoted | remainder”.

As one can guess from what the above shell snippet implies: quoting is handled recursively. Because I’m used to languages with finite stack space and no reliable tail call optimizations; I almost never write recursive functions of any kind, whether they are tco’able or not. Algorithmically, expand_quotes() is a very simple procedure.

It expects to be called with an input line; and treats multiple arguments accordingly (for now). Internally a dispatch table and token stack are maintained; the table contains references to anonymous subroutines, to which the scanned elements are delegated to for the proper expansions.

If no quotes are detected on the line, return the result of expanding it with the default delegate (for unquoted text).

Otherwise break the line on the first set of (matching) quotes.

Any text defined before the beginning quote must be unquoted; apply the default expansion from from the table.

The text between the matching quotes is quoted, apply the appropriate expansion form the table (i.e. ‘, “, or `).

Any text remaining after the matching quotes may or may not be quoted; invoke expand_quotes() on the remainder to find out, and apply the result.

Each expansion applied is pushed onto the token stack in the escaped form it expanded to (i.e. “‘hi bye'” becomes “hi bye”), and the stack is returned to the caller once processing is completed.

With refactoring, the procedure could likely be made tail recursive but I don’t think perl does TCO. Either way, the users fingers or (likely) the machine generating the inputs should run out of stack space before tpsh could pop a cork at the number of quotes lol. An earlier design for expand_quotes() had more in common with finite state machines (in so far as I’ve seen them implemented), but was a lot more contorted then expand_quotes()’ present shape :-/.

Current bugs are handling nested escaped quotes or multiple empty quotes (the spliter) and removing unquoted quotes (addition to delegate sub for unquoted text).

# bugs in expand_quotes
$ echo 'foo "bar'
expand_quotes ': echo | foo "bar |
foo "bar
$ echo "foo "bar"
expand_quotes ": echo | foo | bar"
foo bar"
#
# correct result would have been equal to the previous command
#
$ echo '' "" '' "" '""' '' "" '"' "'"
expand_quotes ': echo | | "" '' "" '""' '' "" '"' "'"
expand_quotes ": " | '' | " '""' '' "" '"' "'"
expand_quotes ': " | "" | '' "" '"' "'"
expand_quotes ': ' | "" | "' "'"
expand_quotes ": "' | ' |
" '' " "" ' "" "' '
#
# correct result would have been: "" " '
# at least, that's how all bourne based shells I
# know about treat it; I would prefer: "" " '
# i.e. without leading whitespace.
#

For some reason this makes me curious, has anyone ever explained why shell syntax allows “”” but not ”’ ? (the results being ” and unclosed quote /or syntax error respectively)

When trying to solve a programming problem, generally I try the most simple solution before I try something more complex: and then evaluate a neater method. I consider the implications solutions have on efficiency, but that is trying to avoid shooting myself in the foot later, rather then trying to optimize the code for a machine.

Some how, I think expanding quotes is just naturally recursive in my crazy brain :-D.

EDIT


commit aeac14bd177a93b84c138a0c62e2cda49e5fe15c
Author: Terry <***snip***>
Date: Tue Apr 7 22:24:35 2009 +0000

bugfix: parameters now expand within quotes via expand_quotes and may be escaped

commit 089fda7cca0049dcabdc8b9659f94dcae417074b
Author: Terry <***snip***>

bugfix: escaped quotes witihn quotes and multiple quotes handled correctly

previous behaviour:

$ echo 'foo "bar'
expand_quotes ': echo | foo "bar |
foo "bar
$ echo "foo "bar"
expand_quotes ": echo | foo | bar"
foo bar"
$ echo '' "" '' "" '""' '' "" '"' "'"
expand_quotes ': echo | | "" '' "" '""' '' "" '"' "'"
expand_quotes ": " | '' | " '""' '' "" '"' "'"
expand_quotes ': " | "" | '' "" '"' "'"
expand_quotes ': ' | "" | "' "'"
expand_quotes ": "' | ' |
" '' " "" ' "" "' '
$

new behaviour:

$ echo 'foo "bar'
expand_quotes ': echo | foo "bar |
foo "bar
$ echo "foo "bar"
expand_quotes ": echo | foo "bar |
foo "bar
$ echo '' "" '' "" '""' '' "" '"' "'"
expand_quotes ': echo | | "" '' "" '""' '' "" '"' "'"
expand_quotes ": | | '' "" '""' '' "" '"' "'"
expand_quotes ': | | "" '""' '' "" '"' "'"
expand_quotes ": | | '""' '' "" '"' "'"
expand_quotes ': | "" | '' "" '"' "'"
expand_quotes ': | | "" '"' "'"
expand_quotes ": | | '"' "'"
expand_quotes ': | " | "'"
expand_quotes ": | ' |
"" " '
$

rofl

http://thedailywtf.com/Articles/The-Super-Hacker.aspx

on man, this ones got me rolling on the floor laughing my butt off – what a great way to make a buck