This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

External Program (mysql) Partyline Interface

Help for those learning Tcl or writing their own scripts.
Post Reply
M
MikeM
Voice
Posts: 2
Joined: Sun Sep 09, 2007 10:11 pm

External Program (mysql) Partyline Interface

Post by MikeM »

Hi,

I'm trying to provide a partyline interface to mysql-client, for convenience, and a bit of interest as to the method.

Basically I want to pipe the i/o to and from the external program (mysql), to display results in the dcc partyline.

Not to be confused, I already use a mysql module for code - I want to emulate the entire mysql client by executing it externally.

After a tip from someone, and looking at user's code on another forum topic, I came up with this:

Code: Select all

bind dcc n mysql mysql_1

proc mysql_1 {h i a} {
     # hack to honor the "must-be-owner" setting:
      *dcc:tcl $h $i [list mysql_2 $h $i $a]
}

proc mysql_2 {h i a} {
      global dbi
      set dbi [open "|mysql -u user --password=pwd db" r+]
      fconfigure $dbi -blocking 0 -buffering line
      fileevent $dbi readable [list gotline $dbi]
      control $i [list mysql_3 $h]
      return "Type 'exit' to return to the real world."
}

proc mysql_3 {h i a} {
      global dbi
         if {$a=="exit"} {
            unset a
            close $dbi
            return 1
         } {
            puts $dbi $a
            flush $dbi
            putserv "privmsg empus :(debug) puts $dbi $a"
           set a ""
         }
         append a \n
      return 0
}

# EDIT: Added this proc for stupid irc clients that
# are incapable of displaying the tab character (\x09)
# Remove it if you don't need it.

proc putdcc {i a} {::putdcc $i [string map {\t "    "} $a]}

proc gotline {dbi} {
 if {![eof $dbi]} {
  if {[gets $dbi] != ""} {
    putserv "privmsg empus :(debug) [gets $dbi]"
    #putdcc $i "mysql: [gets $dbi]"
  }
 }
}

putlog "\[@\] MySQL Interface Loaded."
However, it appears as though gotline is not being triggered - for whatever reason. I get nothing back, which begs the question - is mysql receiving anything in the first place?

Something is wrong here, but I'm not quite sure what... any help would be much appreciated.

Cheers,

-Mike
User avatar
user
 
Posts: 1452
Joined: Tue Mar 18, 2003 9:58 pm
Location: Norway

Re: External Program (mysql) Partyline Interface

Post by user »

MikeM wrote:

Code: Select all

proc gotline {dbi} {
 if {![eof $dbi]} {
  if {[gets $dbi] != ""} {
    putserv "privmsg empus :(debug) [gets $dbi]"
    #putdcc $i "mysql: [gets $dbi]"
  }
 }
}
Try something like this inside the first 'if':

Code: Select all

while {[gets $dbi line]>-1} {putserv "PRIVMSG empus :(debug) $line"}
Have you ever read "The Manual"?
M
MikeM
Voice
Posts: 2
Joined: Sun Sep 09, 2007 10:11 pm

Re: External Program (mysql) Partyline Interface

Post by MikeM »

Doesnt seem to have any effect.

If I put a debug line on the second line of the proc (before first if statement), it enters an endless loop, but never meets the other requirements.

It's as though nothing is coming back from mysql-client (either because the code is wrong, or mysql-client never receives anything in the first place).

[gets $dbi] seems to always return ""

Ideas? Can this even be done?
User avatar
user
 
Posts: 1452
Joined: Tue Mar 18, 2003 9:58 pm
Location: Norway

Post by user »

I added some error handling...try this:

Code: Select all

bind dcc n mysql mysql_init

proc mysql_init {h i a} {
	*dcc:tcl $h $i [list mysql_init2 $h $i $a]
}

proc mysql_init2 {h i a} {
	if {[catch {open "|mysql -u user --password=pwd db" r+} dbi]} {
		return "Open error: $dbi"
	} {
		fconfigure $dbi -blocking 0 -buffering line
		fileevent $dbi readable [list mysql_out $dbi $i]
		control $i [list mysql_in $dbi]
		return "Type 'exit' to return to the real world."
	}
}

proc mysql_in {dbi i a} { 
	if {$a=="exit"||$a==""} { 
		close $dbi
		return 1
	} elseif {[catch {puts $dbi $a; flush $dbi} err]} {
		putdcc $i "Write error: $err"
		close $dbi
		return 1
	} {
		return 0
	}
}

proc mysql_out {dbi i} {
	if {[eof $dbi]} {
		close $dbi
		putdcc $i "EOF."
		control $i {}
	} elseif {[catch {
		while {![fblocked $dbi]&&[gets $dbi line]>-1} {
			putdcc $i $line
		}
	} err]} {
		close $dbi
		putdcc $i "Read error: $err"
		control $i {}
	}
}
(not tested)
Have you ever read "The Manual"?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

There's a couple of argument mismatches in the script.

mysql_in expects three arguments, yet while setting up the fileevent controller, you only define two. Also, the 'control' event is set up to pass one additional argument, which is not supported by mysql_out. Sort those out, and my guess is it'll work like a charm.

Edit:
I would also recommend implementing the bgerror error reporting mechanism when trying to debug scripts using tcl's native event-handler, as errors here tend to go unnoticed due to the very nature of the handler.
NML_375
User avatar
user
 
Posts: 1452
Joined: Tue Mar 18, 2003 9:58 pm
Location: Norway

Post by user »

nml375 wrote:mysql_in expects three arguments, yet while setting up the fileevent controller, you only define two. Also, the 'control' event is set up to pass one additional argument, which is not supported by mysql_out. Sort those out, and my guess is it'll work like a charm.
The fileevent invokes mysql_out, and dcc input is handled by mysql_in, so it seems about right to me (but I'm pretty tired right now, so I might have missed/messed up something :P) Having a bgerror proc is a good idea though, but getting the output to the user under 'control' is a bit messy...
Have you ever read "The Manual"?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Or my head is messed up enough already (with a blocked nose and nice cold)
Would have to agree you've got the arguments right..

As for bgerror, I would just dump the info to the logging facility. Usually should'nt be anything interresting there for your average user, but rather developer and/or botadmin.
NML_375
Post Reply