17c2fbfb3SApril Chin#!/usr/bin/ksh93 27c2fbfb3SApril Chin 37c2fbfb3SApril Chin# 47c2fbfb3SApril Chin# CDDL HEADER START 57c2fbfb3SApril Chin# 67c2fbfb3SApril Chin# The contents of this file are subject to the terms of the 77c2fbfb3SApril Chin# Common Development and Distribution License (the "License"). 87c2fbfb3SApril Chin# You may not use this file except in compliance with the License. 97c2fbfb3SApril Chin# 107c2fbfb3SApril Chin# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 117c2fbfb3SApril Chin# or http://www.opensolaris.org/os/licensing. 127c2fbfb3SApril Chin# See the License for the specific language governing permissions 137c2fbfb3SApril Chin# and limitations under the License. 147c2fbfb3SApril Chin# 157c2fbfb3SApril Chin# When distributing Covered Code, include this CDDL HEADER in each 167c2fbfb3SApril Chin# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 177c2fbfb3SApril Chin# If applicable, add the following below this CDDL HEADER, with the 187c2fbfb3SApril Chin# fields enclosed by brackets "[]" replaced with your own identifying 197c2fbfb3SApril Chin# information: Portions Copyright [yyyy] [name of copyright owner] 207c2fbfb3SApril Chin# 217c2fbfb3SApril Chin# CDDL HEADER END 227c2fbfb3SApril Chin# 237c2fbfb3SApril Chin 247c2fbfb3SApril Chin# 25*3e14f97fSRoger A. Faulkner# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 267c2fbfb3SApril Chin# 277c2fbfb3SApril Chin 287c2fbfb3SApril Chin# 297c2fbfb3SApril Chin# shircbot - a simple IRC client/bot demo 307c2fbfb3SApril Chin# 317c2fbfb3SApril Chin 327c2fbfb3SApril Chin# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 337c2fbfb3SApril Chinexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 347c2fbfb3SApril Chin 357c2fbfb3SApril Chin# Make sure all math stuff runs in the "C" locale to avoid problems 367c2fbfb3SApril Chin# with alternative # radix point representations (e.g. ',' instead of 377c2fbfb3SApril Chin# '.' in de_DE.*-locales). This needs to be set _before_ any 387c2fbfb3SApril Chin# floating-point constants are defined in this script). 397c2fbfb3SApril Chinif [[ "${LC_ALL}" != "" ]] ; then 407c2fbfb3SApril Chin export \ 417c2fbfb3SApril Chin LC_MONETARY="${LC_ALL}" \ 427c2fbfb3SApril Chin LC_MESSAGES="${LC_ALL}" \ 437c2fbfb3SApril Chin LC_COLLATE="${LC_ALL}" \ 447c2fbfb3SApril Chin LC_CTYPE="${LC_ALL}" 457c2fbfb3SApril Chin unset LC_ALL 467c2fbfb3SApril Chinfi 477c2fbfb3SApril Chinexport LC_NUMERIC=C 487c2fbfb3SApril Chin 497c2fbfb3SApril Chinfunction fatal_error 507c2fbfb3SApril Chin{ 517c2fbfb3SApril Chin print -u2 "${progname}: $*" 527c2fbfb3SApril Chin exit 1 537c2fbfb3SApril Chin} 547c2fbfb3SApril Chin 557c2fbfb3SApril Chin# Definition for a IRC session class 567c2fbfb3SApril Chintypeset -T ircsession_t=( 5734f9b3eeSRoland Mainz compound server=( 587c2fbfb3SApril Chin typeset name 597c2fbfb3SApril Chin integer port 607c2fbfb3SApril Chin ) 617c2fbfb3SApril Chin 627c2fbfb3SApril Chin typeset nick="ksh93irc" 637c2fbfb3SApril Chin 647c2fbfb3SApril Chin typeset running=true 657c2fbfb3SApril Chin 667c2fbfb3SApril Chin integer fd=-1 677c2fbfb3SApril Chin 687c2fbfb3SApril Chin function createsession 697c2fbfb3SApril Chin { 707c2fbfb3SApril Chin set -o xtrace 717c2fbfb3SApril Chin 727c2fbfb3SApril Chin _.server.name=$1 737c2fbfb3SApril Chin _.server.port=$2 747c2fbfb3SApril Chin _.nick=$3 757c2fbfb3SApril Chin 767c2fbfb3SApril Chin redirect {_.fd}<> "/dev/tcp/${_.server.name}/${_.server.port}" 777c2fbfb3SApril Chin (( $? == 0 )) || { print -n2 $"Could not open server connection." ; return 1 ; } 787c2fbfb3SApril Chin 797c2fbfb3SApril Chin printf "fd=%d\n" _.fd 807c2fbfb3SApril Chin 817c2fbfb3SApril Chin return 0 827c2fbfb3SApril Chin } 837c2fbfb3SApril Chin 847c2fbfb3SApril Chin function login 857c2fbfb3SApril Chin { 867c2fbfb3SApril Chin { 877c2fbfb3SApril Chin printf "USER %s %s %s %s\n" "${_.nick}" "${_.nick}" "${_.nick}" "${_.nick}" 887c2fbfb3SApril Chin printf "NICK %s\n" "${_.nick}" 897c2fbfb3SApril Chin } >&${_.fd} 907c2fbfb3SApril Chin 917c2fbfb3SApril Chin return 0 927c2fbfb3SApril Chin } 937c2fbfb3SApril Chin 947c2fbfb3SApril Chin function join_channel 957c2fbfb3SApril Chin { 967c2fbfb3SApril Chin printf "JOIN %s\n" "$1" >&${_.fd} 977c2fbfb3SApril Chin 987c2fbfb3SApril Chin return 0 997c2fbfb3SApril Chin } 1007c2fbfb3SApril Chin 1017c2fbfb3SApril Chin function mainloop 1027c2fbfb3SApril Chin { 1037c2fbfb3SApril Chin typeset line 1047c2fbfb3SApril Chin float -S last_tick=0 1057c2fbfb3SApril Chin # We use the linebuf_t class here since network traffic 1067c2fbfb3SApril Chin # isn't guranteed to fit a single $'\n'-terminated line 1077c2fbfb3SApril Chin # into one TCP package. linebuf_t buffers characters 1087c2fbfb3SApril Chin # until it has one complete line. This avoids the need for 1097c2fbfb3SApril Chin # async I/O normally used by IRC clients 1107c2fbfb3SApril Chin linebuf_t serverbuf 1117c2fbfb3SApril Chin linebuf_t clientbuf 1127c2fbfb3SApril Chin integer fd=${_.fd} 1137c2fbfb3SApril Chin 1147c2fbfb3SApril Chin _.login 1157c2fbfb3SApril Chin 1167c2fbfb3SApril Chin while ${_.running} ; do 1177c2fbfb3SApril Chin while serverbuf.readbuf line <&${fd} ; do 1187c2fbfb3SApril Chin _.dispatch_serverevent "$line" 1197c2fbfb3SApril Chin done 1207c2fbfb3SApril Chin 1217c2fbfb3SApril Chin while clientbuf.readbuf line </dev/stdin ; do 1227c2fbfb3SApril Chin printf "client: %q\n" "${line}" 1237c2fbfb3SApril Chin printf "%s\n" "${line}" >&${fd} 1247c2fbfb3SApril Chin done 1257c2fbfb3SApril Chin 1267c2fbfb3SApril Chin # call mainloop_tick function in intervals to handle 1277c2fbfb3SApril Chin # async events (e.g. automatic /join etc.) 1287c2fbfb3SApril Chin if (( (SECONDS-last_tick) > 5. )) ; then 1297c2fbfb3SApril Chin (( last_tick=SECONDS )) 1307c2fbfb3SApril Chin _.mainloop_tick 1317c2fbfb3SApril Chin fi 1327c2fbfb3SApril Chin done 1337c2fbfb3SApril Chin 1347c2fbfb3SApril Chin return 0 1357c2fbfb3SApril Chin } 1367c2fbfb3SApril Chin 1377c2fbfb3SApril Chin function mainloop_tick 1387c2fbfb3SApril Chin { 1397c2fbfb3SApril Chin return 0 1407c2fbfb3SApril Chin } 1417c2fbfb3SApril Chin 1427c2fbfb3SApril Chin function dispatch_serverevent 1437c2fbfb3SApril Chin { 1447c2fbfb3SApril Chin typeset line="$1" 1457c2fbfb3SApril Chin 1467c2fbfb3SApril Chin case "${line}" in 1477c2fbfb3SApril Chin ~(El)PING) 14834f9b3eeSRoland Mainz compound ping_args=( 1497c2fbfb3SApril Chin line="$line" 1507c2fbfb3SApril Chin ) 1517c2fbfb3SApril Chin _.serverevent_ping "ping_args" 1527c2fbfb3SApril Chin ;; 1537c2fbfb3SApril Chin ~(El):.*\ PRIVMSG) 15434f9b3eeSRoland Mainz compound privmsg_args=( 1557c2fbfb3SApril Chin typeset line="$line" 1567c2fbfb3SApril Chin typeset msguser="${line/~(Elr)([^ ]+) ([^ ]+) ([^ ]+) (.*)/\1}" 1577c2fbfb3SApril Chin typeset msgchannel="${line/~(Elr)([^ ]+) ([^ ]+) ([^ ]+) (.*)/\3}" 1587c2fbfb3SApril Chin typeset msg="${line/~(Elr)([^ ]+) ([^ ]+) ([^ ]+) (.*)/\4}" 1597c2fbfb3SApril Chin ) 1607c2fbfb3SApril Chin _.serverevent_privmsg "privmsg_args" 1617c2fbfb3SApril Chin ;; 1627c2fbfb3SApril Chin ~(El):.*\ INVITE) 16334f9b3eeSRoland Mainz compound invite_args=( 1647c2fbfb3SApril Chin typeset line="$line" 1657c2fbfb3SApril Chin typeset inviteuser="${line/~(Elr)([^ ]+) ([^ ]+) ([^ ]+) (.*)/\1}" 1667c2fbfb3SApril Chin typeset invitenick="${line/~(Elr)([^ ]+) ([^ ]+) ([^ ]+) (.*)/\3}" 1677c2fbfb3SApril Chin typeset invitechannel="${line/~(Elr)([^ ]+) ([^ ]+) ([^ ]+) (.*)/\4}" 1687c2fbfb3SApril Chin ) 1697c2fbfb3SApril Chin _.serverevent_invite "invite_args" 1707c2fbfb3SApril Chin ;; 1717c2fbfb3SApril Chin *) 1727c2fbfb3SApril Chin printf "server: %q\n" "${line}" 1737c2fbfb3SApril Chin ;; 1747c2fbfb3SApril Chin esac 1757c2fbfb3SApril Chin 1767c2fbfb3SApril Chin return 0 1777c2fbfb3SApril Chin } 1787c2fbfb3SApril Chin 1797c2fbfb3SApril Chin function serverevent_privmsg 1807c2fbfb3SApril Chin { 1817c2fbfb3SApril Chin nameref args=$1 1827c2fbfb3SApril Chin typeset msguser="${args.msguser}" 1837c2fbfb3SApril Chin typeset msgchannel="${args.msgchannel}" 1847c2fbfb3SApril Chin typeset msg="${args.msg}" 1857c2fbfb3SApril Chin 1867c2fbfb3SApril Chin printf "#privms: user=%q, channel=%q, msg=%q\n" "$msguser" "$msgchannel" "$msg" 1877c2fbfb3SApril Chin 1887c2fbfb3SApril Chin return 0 1897c2fbfb3SApril Chin } 1907c2fbfb3SApril Chin 1917c2fbfb3SApril Chin function serverevent_invite 1927c2fbfb3SApril Chin { 1937c2fbfb3SApril Chin nameref args=$1 1947c2fbfb3SApril Chin 1957c2fbfb3SApril Chin printf "JOIN %s\n" "${args.invitechannel/:/}" >&${_.fd} 1967c2fbfb3SApril Chin 1977c2fbfb3SApril Chin return 0 1987c2fbfb3SApril Chin } 1997c2fbfb3SApril Chin 2007c2fbfb3SApril Chin function send_privmsg 2017c2fbfb3SApril Chin { 2027c2fbfb3SApril Chin typeset channel="$1" 2037c2fbfb3SApril Chin typeset msg="$2" 2047c2fbfb3SApril Chin 2057c2fbfb3SApril Chin # Do we have to escape any characters in "msg" ? 2067c2fbfb3SApril Chin printf "PRIVMSG %s :%s\n" "${channel}" "${msg}" >&${_.fd} 2077c2fbfb3SApril Chin 2087c2fbfb3SApril Chin return 0 2097c2fbfb3SApril Chin } 2107c2fbfb3SApril Chin 2117c2fbfb3SApril Chin function serverevent_ping 2127c2fbfb3SApril Chin { 2137c2fbfb3SApril Chin nameref args=$1 2147c2fbfb3SApril Chin 2157c2fbfb3SApril Chin printf "PONG %s\n" "${args.line/~(Elr)([^ ]+) ([^ ]+).*/\2}" >&${_.fd} 2167c2fbfb3SApril Chin 2177c2fbfb3SApril Chin return 0 2187c2fbfb3SApril Chin } 2197c2fbfb3SApril Chin) 2207c2fbfb3SApril Chin 2217c2fbfb3SApril Chin# line buffer class 2227c2fbfb3SApril Chin# The buffer class tries to read characters from the given <fd> until 2237c2fbfb3SApril Chin# it has read a whole line. 2247c2fbfb3SApril Chintypeset -T linebuf_t=( 2257c2fbfb3SApril Chin typeset buf 2267c2fbfb3SApril Chin 2277c2fbfb3SApril Chin function reset 2287c2fbfb3SApril Chin { 2297c2fbfb3SApril Chin _.buf="" 2307c2fbfb3SApril Chin return 0 2317c2fbfb3SApril Chin } 2327c2fbfb3SApril Chin 2337c2fbfb3SApril Chin function readbuf 2347c2fbfb3SApril Chin { 2357c2fbfb3SApril Chin nameref var=$1 2367c2fbfb3SApril Chin typeset ch 2377c2fbfb3SApril Chin 2387c2fbfb3SApril Chin while IFS='' read -t 0.2 -N 1 ch ; do 2397c2fbfb3SApril Chin [[ "$ch" == $'\r' ]] && continue 2407c2fbfb3SApril Chin 2417c2fbfb3SApril Chin if [[ "$ch" == $'\n' ]] ; then 2427c2fbfb3SApril Chin var="${_.buf}" 2437c2fbfb3SApril Chin _.reset 2447c2fbfb3SApril Chin return 0 2457c2fbfb3SApril Chin fi 2467c2fbfb3SApril Chin 2477c2fbfb3SApril Chin _.buf+="$ch" 2487c2fbfb3SApril Chin done 2497c2fbfb3SApril Chin 2507c2fbfb3SApril Chin return 1 2517c2fbfb3SApril Chin } 2527c2fbfb3SApril Chin) 2537c2fbfb3SApril Chin 2547c2fbfb3SApril Chinfunction usage 2557c2fbfb3SApril Chin{ 2567c2fbfb3SApril Chin OPTIND=0 2577c2fbfb3SApril Chin getopts -a "${progname}" "${shircbot_usage}" OPT '-?' 2587c2fbfb3SApril Chin exit 2 2597c2fbfb3SApril Chin} 2607c2fbfb3SApril Chin 2617c2fbfb3SApril Chin# program start 2627c2fbfb3SApril Chin# (be carefull with builtins here - they are unconditionally available 2637c2fbfb3SApril Chin# in the shell's "restricted" mode) 2647c2fbfb3SApril Chinbuiltin basename 2657c2fbfb3SApril Chinbuiltin sum 2667c2fbfb3SApril Chin 2677c2fbfb3SApril Chintypeset progname="${ basename "${0}" ; }" 2687c2fbfb3SApril Chin 2697c2fbfb3SApril Chintypeset -r shircbot_usage=$'+ 27034f9b3eeSRoland Mainz[-?\n@(#)\$Id: shircbot (Roland Mainz) 2009-09-09 \$\n] 2717c2fbfb3SApril Chin[-author?Roland Mainz <roland.mainz@sun.com>] 2727c2fbfb3SApril Chin[-author?Roland Mainz <roland.mainz@nrubsig.org>] 2737c2fbfb3SApril Chin[+NAME?shircbot - simple IRC bot demo] 2747c2fbfb3SApril Chin[+DESCRIPTION?\bshircbot\b is a small demo IRC bot which provides 2757c2fbfb3SApril Chin a simple IRC bot with several subcommands.] 2767c2fbfb3SApril Chin[n:nickname?IRC nickname for this bot.]:[nick] 2777c2fbfb3SApril Chin[s:ircserver?IRC servername.]:[servername] 2787c2fbfb3SApril Chin[j:joinchannel?IRC servername.]:[channelname] 2797c2fbfb3SApril Chin[+SEE ALSO?\bksh93\b(1)] 2807c2fbfb3SApril Chin' 2817c2fbfb3SApril Chin 28234f9b3eeSRoland Mainzcompound config=( 2837c2fbfb3SApril Chin typeset nickname="${LOGNAME}bot" 2847c2fbfb3SApril Chin typeset servername="irc.freenode.net" 2857c2fbfb3SApril Chin integer port=6667 2867c2fbfb3SApril Chin typeset -a join_channels 2877c2fbfb3SApril Chin) 2887c2fbfb3SApril Chin 2897c2fbfb3SApril Chinwhile getopts -a "${progname}" "${shircbot_usage}" OPT ; do 2907c2fbfb3SApril Chin# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 2917c2fbfb3SApril Chin case ${OPT} in 2927c2fbfb3SApril Chin n) config.nickname="${OPTARG}" ;; 2937c2fbfb3SApril Chin s) config.servername="${OPTARG}" ;; 2947c2fbfb3SApril Chin j) config.join_channels+=( "${OPTARG}" ) ;; 2957c2fbfb3SApril Chin *) usage ;; 2967c2fbfb3SApril Chin esac 2977c2fbfb3SApril Chindone 2987c2fbfb3SApril Chinshift $((OPTIND-1)) 2997c2fbfb3SApril Chin 3007c2fbfb3SApril Chin# if no channel was provided we join a predefined set of channels 3017c2fbfb3SApril Chinif (( ${#config.join_channels[@]} == 0 )) ; then 3027c2fbfb3SApril Chin if [[ "${config.servername}" == "irc.freenode.net" ]] ; then 3037c2fbfb3SApril Chin config.join_channels+=( "#opensolaris" ) 3047c2fbfb3SApril Chin config.join_channels+=( "#opensolaris-dev" ) 3057c2fbfb3SApril Chin config.join_channels+=( "#opensolaris-arc" ) 30634f9b3eeSRoland Mainz config.join_channels+=( "#opensolaris-meeting" ) 30734f9b3eeSRoland Mainz config.join_channels+=( "#ospkg" ) 3087c2fbfb3SApril Chin config.join_channels+=( "#ksh" ) 3097c2fbfb3SApril Chin elif [[ "${config.servername}" == ~(E)irc.(sfbay|sweden) ]] ; then 3107c2fbfb3SApril Chin config.join_channels+=( "#onnv" ) 3117c2fbfb3SApril Chin fi 3127c2fbfb3SApril Chinfi 3137c2fbfb3SApril Chin 3147c2fbfb3SApril Chinprint "## Start." 3157c2fbfb3SApril Chin 3167c2fbfb3SApril Chinircsession_t mybot 3177c2fbfb3SApril Chin 3187c2fbfb3SApril Chin# override ircsession_t::serverevent_privmsg with a new method for our bot 3197c2fbfb3SApril Chinfunction mybot.serverevent_privmsg 3207c2fbfb3SApril Chin{ 3217c2fbfb3SApril Chin nameref args=$1 3227c2fbfb3SApril Chin typeset msguser="${args.msguser}" 3237c2fbfb3SApril Chin typeset msgchannel="${args.msgchannel}" 3247c2fbfb3SApril Chin typeset msg="${args.msg}" 3257c2fbfb3SApril Chin 3267c2fbfb3SApril Chin printf "#message: user=%q, channel=%q, msg=%q\n" "$msguser" "$msgchannel" "$msg" 3277c2fbfb3SApril Chin 3287c2fbfb3SApril Chin # Check if we get a private message 3297c2fbfb3SApril Chin if [[ "${msgchannel}" == "${_.nick}" ]] ; then 3307c2fbfb3SApril Chin # ${msgchannel} point to our own nick if we got a private message, 3317c2fbfb3SApril Chin # we need to extract the sender's nickname from ${msguser} and put 3327c2fbfb3SApril Chin # it into msgchannel 3337c2fbfb3SApril Chin msgchannel="${msguser/~(El):(.*)!.*/\1}" 3347c2fbfb3SApril Chin else 3357c2fbfb3SApril Chin # check if this is a command for this bot 3367c2fbfb3SApril Chin [[ "$msg" != ~(Eli):${_.nick}:[[:space:]] ]] && return 0 3377c2fbfb3SApril Chin fi 3387c2fbfb3SApril Chin 3397c2fbfb3SApril Chin # strip beginning (e.g. ":<nick>:" or ":") plus extra spaces 3407c2fbfb3SApril Chin msg="${msg/~(Eli)(:${_.nick})*:[[:space:]]*/}" 3417c2fbfb3SApril Chin 3427c2fbfb3SApril Chin printf "botmsg=%q\n" "$msg" 3437c2fbfb3SApril Chin 3447c2fbfb3SApril Chin case "$msg" in 3457c2fbfb3SApril Chin ~(Eli)date) 34634f9b3eeSRoland Mainz _.send_privmsg "$msgchannel" "${ 34734f9b3eeSRoland Mainz printf "%(%Y-%m-%d, %Th/%Z)T\n" 34834f9b3eeSRoland Mainz }" 3497c2fbfb3SApril Chin ;; 3507c2fbfb3SApril Chin ~(Eli)echo) 3517c2fbfb3SApril Chin _.send_privmsg "$msgchannel" "${msg#*echo}" 3527c2fbfb3SApril Chin ;; 3537c2fbfb3SApril Chin ~(Eli)exitbot) 3547c2fbfb3SApril Chin typeset exitkey="$(print "$msguser" | sum -x sha1)" # this is unwise&&insecure 3557c2fbfb3SApril Chin if [[ "$msg" == *${exitkey}* ]] ; then 3567c2fbfb3SApril Chin _.running=false 3577c2fbfb3SApril Chin fi 3587c2fbfb3SApril Chin ;; 3597c2fbfb3SApril Chin ~(Eli)help) 36034f9b3eeSRoland Mainz _.send_privmsg "$msgchannel" "${ 3617c2fbfb3SApril Chin printf "Hello, this is shircbot, written in ksh93 (%s). " "${.sh.version}" 3627c2fbfb3SApril Chin printf "Subcommands are 'say hello', 'math <math-expr>', 'stocks', 'uuid', 'date' and 'echo'." 36334f9b3eeSRoland Mainz }" 3647c2fbfb3SApril Chin ;; 3657c2fbfb3SApril Chin ~(Eli)math) 3667c2fbfb3SApril Chin if [[ "${msg}" == ~(E)[\`\$] ]] ; then 3677c2fbfb3SApril Chin # "restricted" shell mode would prevent any damage but we try to be carefull... 3687c2fbfb3SApril Chin _.send_privmsg "$msgchannel" "Syntax error." 3697c2fbfb3SApril Chin else 3707c2fbfb3SApril Chin typeset mathexpr="${msg#*math}" 3717c2fbfb3SApril Chin 3727c2fbfb3SApril Chin printf "Calculating '%s'\n" "${mathexpr}" 37334f9b3eeSRoland Mainz _.send_privmsg "$msgchannel" "${ 37434f9b3eeSRoland Mainz ( printf 'export PATH=/usr/${RANDOM}/$$/${RANDOM}/foo ; set -o restricted ; printf "%%s = %%.40g\n" "%s" $(( %s ))\n' "${mathexpr}" "${mathexpr}" | source /dev/stdin 2>&1 ) 37534f9b3eeSRoland Mainz }" 3767c2fbfb3SApril Chin fi 3777c2fbfb3SApril Chin ;; 3787c2fbfb3SApril Chin ~(Eli)say\ hello) 3797c2fbfb3SApril Chin _.send_privmsg "$msgchannel" "Hello, this is a bot." 3807c2fbfb3SApril Chin ;; 3817c2fbfb3SApril Chin ~(Eli)stocks) 3827c2fbfb3SApril Chin typeset stockmsg tickersymbol 38334f9b3eeSRoland Mainz for tickersymbol in "JAVA" "ORCL" "IBM" "AAPL" "HPQ" ; do 3847c2fbfb3SApril Chin stockmsg="$( /usr/sfw/bin/wget -q -O /dev/stdout "http://quote.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&e=.csv&s=${tickersymbol}" 2>&1 )" 3857c2fbfb3SApril Chin _.send_privmsg "$msgchannel" "${tickersymbol}: ${stockmsg//,/ }" 3867c2fbfb3SApril Chin done 3877c2fbfb3SApril Chin ;; 3887c2fbfb3SApril Chin ~(Eli)uuid) 38934f9b3eeSRoland Mainz _.send_privmsg "$msgchannel" "${ 39034f9b3eeSRoland Mainz print "%(%Y%M%D%S%N)T$((RANDOM))%s\n" "${msguser}" | sum -x sha256 39134f9b3eeSRoland Mainz }" 3927c2fbfb3SApril Chin ;; 3937c2fbfb3SApril Chin esac 3947c2fbfb3SApril Chin 3957c2fbfb3SApril Chin return 0 3967c2fbfb3SApril Chin} 3977c2fbfb3SApril Chin 3987c2fbfb3SApril Chin# Automatically join the list of channels listed in |config.join_channels| 3997c2fbfb3SApril Chin# after the client is connected to the server for some time 4007c2fbfb3SApril Chinfunction mybot.mainloop_tick 4017c2fbfb3SApril Chin{ 4027c2fbfb3SApril Chin integer -S autojoin_done=2 4037c2fbfb3SApril Chin integer i 4047c2fbfb3SApril Chin 4057c2fbfb3SApril Chin if (( autojoin_done-- == 0 && ${#config.join_channels[@]} > 0 )) ; then 4067c2fbfb3SApril Chin print "# Autojoin channels..." 4077c2fbfb3SApril Chin 4087c2fbfb3SApril Chin for ((i=0 ; i < ${#config.join_channels[@]} ; i++ )) ; do 4097c2fbfb3SApril Chin mybot.join_channel "${config.join_channels[i]}" 4107c2fbfb3SApril Chin done 4117c2fbfb3SApril Chin fi 4127c2fbfb3SApril Chin 4137c2fbfb3SApril Chin return 0 4147c2fbfb3SApril Chin} 4157c2fbfb3SApril Chin 4167c2fbfb3SApril Chinmybot.createsession "${config.servername}" ${config.port} "${config.nickname}" 4177c2fbfb3SApril Chin 4187c2fbfb3SApril Chin# This is a network-facing application - once we've set eveything up 4197c2fbfb3SApril Chin# we set PATH to a random value and switch to the shell's restricted 4207c2fbfb3SApril Chin# mode to make sure noone can escape the jail. 4217c2fbfb3SApril Chin#export PATH=/usr/$RANDOM/foo 4227c2fbfb3SApril Chin#set -o restricted 4237c2fbfb3SApril Chin 4247c2fbfb3SApril Chinmybot.mainloop 4257c2fbfb3SApril Chin 4267c2fbfb3SApril Chinprint "## End." 4277c2fbfb3SApril Chin 4287c2fbfb3SApril Chinexit 0 429