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.

utimer with an if statement

Help for those learning Tcl or writing their own scripts.
Post Reply
j
johne
Voice
Posts: 29
Joined: Tue Jul 19, 2005 2:24 am

utimer with an if statement

Post by johne »

i have a join bind which calls a proc with the usual n u h c args, when the following line is performed, i get an error

Code: Select all

utimer $::timer1 [list if {[onchan $n $c] && ![isop $n $c]} { putserv "PRIVMSG $c :[string map -nocase "%n $n" [random $::line1]]" }]

can't read "n": no such variable
any ideas why it wouldnt be able to find the $nick var?

Thanks
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

It is because n is not available in globalspace when the timer triggers..

This requires an in-depth understanding of the command and variable substitutions done by the tcl interpreter. Roughly put however, any parameter enclosed with {} will not be processed for variable nor command substitutions, but instead passed on to the command as is.
In your case, both the condition and if_true parameters are enclosed with {}, and neither have any variable substitutions within the proc. When the timer triggers, the commandline is executed. The if-command then evaluates the first parameter (in the same fashion as calling eval) and tests the result; this will trigger both command and variable substitutions. However, neither n or c are now available, as the nameless space in the proc that created the timer has now been destroyed. Same applies for the if_true parameter.

Solving this, unfortunately, is not as easy as replacing {} with "", as it is very easy to accidentally pass the content of c and n to the interpreter, and unwanted substitutions are done - possibly leading to both your eggdrop and shell being compromised.
One way around this could be to save the values into some globalspace variable or array, and only pass an id to the timer-code rather than the variable contents. Since you're in control of the id, you could craft it in such manner that it is "safe". This would of course add some overhead to your script in order to maintain and clear this "storage"...
NML_375
j
johne
Voice
Posts: 29
Joined: Tue Jul 19, 2005 2:24 am

Re: utimer with an if statement

Post by johne »

ahh :/ thanks for your explanation.
r
r0t3n
Owner
Posts: 507
Joined: Tue May 31, 2005 6:56 pm
Location: UK

Post by r0t3n »

Why not just create a seperate proc.. and call it with var arguments..

Code: Select all

proc dostuff {n c line} {
    if {[onchan $n $c] && ![isop $n $c]} {
        putserv "PRIVMSG $c :[string map -nocase { %n $n } [random $line]]"
    }
}
and call it with:

Code: Select all

utimer $::timer1 [list dostuff $n $c $::line1]
This saves creating an array, id system, updating and removal of such id's from the array, and generally more understanding and simple..
r0t3n @ #r0t3n @ Quakenet
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

You're right, Tosser.. :)

Curse of the tcl-wizard at work again:
Always overwork things overlooking the very simple solutions.
NML_375
Post Reply