18462SApril.Chin@Sun.COM#!/usr/bin/ksh93 28462SApril.Chin@Sun.COM 38462SApril.Chin@Sun.COM# 48462SApril.Chin@Sun.COM# CDDL HEADER START 58462SApril.Chin@Sun.COM# 68462SApril.Chin@Sun.COM# The contents of this file are subject to the terms of the 78462SApril.Chin@Sun.COM# Common Development and Distribution License (the "License"). 88462SApril.Chin@Sun.COM# You may not use this file except in compliance with the License. 98462SApril.Chin@Sun.COM# 108462SApril.Chin@Sun.COM# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 118462SApril.Chin@Sun.COM# or http://www.opensolaris.org/os/licensing. 128462SApril.Chin@Sun.COM# See the License for the specific language governing permissions 138462SApril.Chin@Sun.COM# and limitations under the License. 148462SApril.Chin@Sun.COM# 158462SApril.Chin@Sun.COM# When distributing Covered Code, include this CDDL HEADER in each 168462SApril.Chin@Sun.COM# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 178462SApril.Chin@Sun.COM# If applicable, add the following below this CDDL HEADER, with the 188462SApril.Chin@Sun.COM# fields enclosed by brackets "[]" replaced with your own identifying 198462SApril.Chin@Sun.COM# information: Portions Copyright [yyyy] [name of copyright owner] 208462SApril.Chin@Sun.COM# 218462SApril.Chin@Sun.COM# CDDL HEADER END 228462SApril.Chin@Sun.COM# 238462SApril.Chin@Sun.COM 248462SApril.Chin@Sun.COM# 25*10898Sroland.mainz@nrubsig.org# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 268462SApril.Chin@Sun.COM# Use is subject to license terms. 278462SApril.Chin@Sun.COM# 288462SApril.Chin@Sun.COM 298462SApril.Chin@Sun.COM# 308462SApril.Chin@Sun.COM# rssread - a simple RSS2.0 reader with RSS to XHTML to 318462SApril.Chin@Sun.COM# plaintext conversion. 328462SApril.Chin@Sun.COM# 338462SApril.Chin@Sun.COM 348462SApril.Chin@Sun.COM# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 358462SApril.Chin@Sun.COMexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 368462SApril.Chin@Sun.COM 378462SApril.Chin@Sun.COMfunction printmsg 388462SApril.Chin@Sun.COM{ 398462SApril.Chin@Sun.COM print -u2 "$*" 408462SApril.Chin@Sun.COM} 418462SApril.Chin@Sun.COM 428462SApril.Chin@Sun.COMfunction debugmsg 438462SApril.Chin@Sun.COM{ 448462SApril.Chin@Sun.COM# printmsg "$*" 458462SApril.Chin@Sun.COMtrue 468462SApril.Chin@Sun.COM} 478462SApril.Chin@Sun.COM 488462SApril.Chin@Sun.COMfunction fatal_error 498462SApril.Chin@Sun.COM{ 508462SApril.Chin@Sun.COM print -u2 "${progname}: $*" 518462SApril.Chin@Sun.COM exit 1 528462SApril.Chin@Sun.COM} 538462SApril.Chin@Sun.COM 54*10898Sroland.mainz@nrubsig.orgtypeset -T urlconnection_t=( 55*10898Sroland.mainz@nrubsig.org # public 56*10898Sroland.mainz@nrubsig.org typeset user_agent="ksh93/urlconnection_t" 57*10898Sroland.mainz@nrubsig.org 58*10898Sroland.mainz@nrubsig.org # private variables 59*10898Sroland.mainz@nrubsig.org typeset protocol 60*10898Sroland.mainz@nrubsig.org typeset path1 61*10898Sroland.mainz@nrubsig.org typeset host 62*10898Sroland.mainz@nrubsig.org typeset path 63*10898Sroland.mainz@nrubsig.org typeset port 64*10898Sroland.mainz@nrubsig.org 65*10898Sroland.mainz@nrubsig.org compound netfd=( 66*10898Sroland.mainz@nrubsig.org integer in=-1 # incoming traffic 67*10898Sroland.mainz@nrubsig.org integer out=-1 # outgoing traffic 68*10898Sroland.mainz@nrubsig.org ) 698462SApril.Chin@Sun.COM 70*10898Sroland.mainz@nrubsig.org # only used for https 71*10898Sroland.mainz@nrubsig.org compound ssl=( 72*10898Sroland.mainz@nrubsig.org compound fifo=( 73*10898Sroland.mainz@nrubsig.org typeset dir="" 74*10898Sroland.mainz@nrubsig.org typeset in="" 75*10898Sroland.mainz@nrubsig.org typeset out="" 76*10898Sroland.mainz@nrubsig.org ) 77*10898Sroland.mainz@nrubsig.org integer openssl_client_pid=-1 78*10898Sroland.mainz@nrubsig.org ) 79*10898Sroland.mainz@nrubsig.org 80*10898Sroland.mainz@nrubsig.org # parse HTTP return code, cookies etc. 81*10898Sroland.mainz@nrubsig.org function parse_http_response 82*10898Sroland.mainz@nrubsig.org { 83*10898Sroland.mainz@nrubsig.org nameref response="$1" 84*10898Sroland.mainz@nrubsig.org typeset h statuscode statusmsg i 85*10898Sroland.mainz@nrubsig.org 86*10898Sroland.mainz@nrubsig.org # we use '\r' as additional IFS to filter the final '\r' 87*10898Sroland.mainz@nrubsig.org IFS=$' \t\r' read -r h statuscode statusmsg # read HTTP/1.[01] <code> 88*10898Sroland.mainz@nrubsig.org [[ "$h" != ~(Eil)HTTP/.* ]] && { print -u2 -f $"%s: HTTP/ header missing\n" "$0" ; return 1 ; } 89*10898Sroland.mainz@nrubsig.org [[ "$statuscode" != ~(Elr)[0-9]* ]] && { print -u2 -f $"%s: invalid status code\n" "$0" ; return 1 ; } 90*10898Sroland.mainz@nrubsig.org response.statuscode="$statuscode" 91*10898Sroland.mainz@nrubsig.org response.statusmsg="$statusmsg" 92*10898Sroland.mainz@nrubsig.org 93*10898Sroland.mainz@nrubsig.org # skip remaining headers 94*10898Sroland.mainz@nrubsig.org while IFS='' read -r i ; do 95*10898Sroland.mainz@nrubsig.org [[ "$i" == $'\r' ]] && break 968462SApril.Chin@Sun.COM 97*10898Sroland.mainz@nrubsig.org # strip '\r' at the end 98*10898Sroland.mainz@nrubsig.org i="${i/~(Er)$'\r'/}" 998462SApril.Chin@Sun.COM 100*10898Sroland.mainz@nrubsig.org case "$i" in 101*10898Sroland.mainz@nrubsig.org ~(Eli)Content-Type:.*) 102*10898Sroland.mainz@nrubsig.org response.content_type="${i/~(El).*:[[:blank:]]*/}" 103*10898Sroland.mainz@nrubsig.org ;; 104*10898Sroland.mainz@nrubsig.org ~(Eli)Content-Length:[[:blank:]]*[0-9]*) 105*10898Sroland.mainz@nrubsig.org integer response.content_length="${i/~(El).*:[[:blank:]]*/}" 106*10898Sroland.mainz@nrubsig.org ;; 107*10898Sroland.mainz@nrubsig.org ~(Eli)Transfer-Encoding:.*) 108*10898Sroland.mainz@nrubsig.org response.transfer_encoding="${i/~(El).*:[[:blank:]]*/}" 109*10898Sroland.mainz@nrubsig.org ;; 110*10898Sroland.mainz@nrubsig.org esac 111*10898Sroland.mainz@nrubsig.org done 112*10898Sroland.mainz@nrubsig.org 113*10898Sroland.mainz@nrubsig.org return 0 114*10898Sroland.mainz@nrubsig.org } 1158462SApril.Chin@Sun.COM 116*10898Sroland.mainz@nrubsig.org function cat_http_body 117*10898Sroland.mainz@nrubsig.org { 118*10898Sroland.mainz@nrubsig.org typeset emode="$1" 119*10898Sroland.mainz@nrubsig.org typeset hexchunksize="0" 120*10898Sroland.mainz@nrubsig.org integer chunksize=0 121*10898Sroland.mainz@nrubsig.org 122*10898Sroland.mainz@nrubsig.org if [[ "${emode}" == "chunked" ]] ; then 123*10898Sroland.mainz@nrubsig.org while IFS=$'\n' read hexchunksize ; do 124*10898Sroland.mainz@nrubsig.org hexchunksize="${hexchunksize//$'\r'/}" 125*10898Sroland.mainz@nrubsig.org [[ "${hexchunksize}" != "" ]] || continue 126*10898Sroland.mainz@nrubsig.org [[ "${hexchunksize}" == ~(Elri)[0-9abcdef]+ ]] || break 127*10898Sroland.mainz@nrubsig.org (( chunksize=16#${hexchunksize} )) 128*10898Sroland.mainz@nrubsig.org (( chunksize > 0 )) || break 129*10898Sroland.mainz@nrubsig.org dd bs=1 count="${chunksize}" 2>/dev/null 130*10898Sroland.mainz@nrubsig.org done 131*10898Sroland.mainz@nrubsig.org else 132*10898Sroland.mainz@nrubsig.org cat 133*10898Sroland.mainz@nrubsig.org fi 134*10898Sroland.mainz@nrubsig.org 135*10898Sroland.mainz@nrubsig.org return 0 136*10898Sroland.mainz@nrubsig.org } 137*10898Sroland.mainz@nrubsig.org 138*10898Sroland.mainz@nrubsig.org function init_url 139*10898Sroland.mainz@nrubsig.org { 140*10898Sroland.mainz@nrubsig.org _.protocol="${1%://*}" 141*10898Sroland.mainz@nrubsig.org _.path1="${1#*://}" # "http://foo.bat.net/x/y.html" ----> "foo.bat.net/x/y.html" 1428462SApril.Chin@Sun.COM 143*10898Sroland.mainz@nrubsig.org if [[ "${_.protocol}" == ~(Elr)http(|s) ]] ; then 144*10898Sroland.mainz@nrubsig.org _.host="${_.path1%%/*}" 145*10898Sroland.mainz@nrubsig.org _.path="${_.path1#*/}" 146*10898Sroland.mainz@nrubsig.org _.port="${_.host##*:}" 147*10898Sroland.mainz@nrubsig.org fi 148*10898Sroland.mainz@nrubsig.org 149*10898Sroland.mainz@nrubsig.org return 0 150*10898Sroland.mainz@nrubsig.org } 151*10898Sroland.mainz@nrubsig.org 152*10898Sroland.mainz@nrubsig.org # close connection 153*10898Sroland.mainz@nrubsig.org function close_connection 154*10898Sroland.mainz@nrubsig.org { 155*10898Sroland.mainz@nrubsig.org integer ret 156*10898Sroland.mainz@nrubsig.org 157*10898Sroland.mainz@nrubsig.org if (( _.netfd.in != -1 )) ; then 158*10898Sroland.mainz@nrubsig.org redirect {_.netfd.in}<&- 159*10898Sroland.mainz@nrubsig.org (( _.netfd.in=-1 )) 160*10898Sroland.mainz@nrubsig.org fi 161*10898Sroland.mainz@nrubsig.org 162*10898Sroland.mainz@nrubsig.org if (( _.netfd.in != _.netfd.out && _.netfd.out != -1 )) ; then 163*10898Sroland.mainz@nrubsig.org redirect {_.netfd.out}<&- 164*10898Sroland.mainz@nrubsig.org (( _.netfd.out=-1 )) 165*10898Sroland.mainz@nrubsig.org fi 1668462SApril.Chin@Sun.COM 167*10898Sroland.mainz@nrubsig.org if [[ "${_.protocol}" == "https" ]] ; then 168*10898Sroland.mainz@nrubsig.org wait ${_.ssl.openssl_client_pid} || { print -u2 -f "%s: openssl failed.\n" ; return 1 ; } 169*10898Sroland.mainz@nrubsig.org (( _.ssl.openssl_client_pid=-1 )) 170*10898Sroland.mainz@nrubsig.org 171*10898Sroland.mainz@nrubsig.org rm -r \"${_.ssl.fifo.dir}\" 172*10898Sroland.mainz@nrubsig.org _.ssl.fifo.dir="" 173*10898Sroland.mainz@nrubsig.org fi 174*10898Sroland.mainz@nrubsig.org 175*10898Sroland.mainz@nrubsig.org return 0 176*10898Sroland.mainz@nrubsig.org } 177*10898Sroland.mainz@nrubsig.org 178*10898Sroland.mainz@nrubsig.org function open_connection 179*10898Sroland.mainz@nrubsig.org { 180*10898Sroland.mainz@nrubsig.org if [[ "${_.protocol}" == "https" ]] ; then 181*10898Sroland.mainz@nrubsig.org _.ssl.fifo.dir="$(mktemp -d)" 182*10898Sroland.mainz@nrubsig.org _.ssl.fifo.in="${_.ssl.fifo.dir}/in" 183*10898Sroland.mainz@nrubsig.org _.ssl.fifo.out="${_.ssl.fifo.dir}/out" 1848462SApril.Chin@Sun.COM 185*10898Sroland.mainz@nrubsig.org # Use "errexit" to leave it at the first error 186*10898Sroland.mainz@nrubsig.org # (this saves lots of if/fi tests for error checking) 187*10898Sroland.mainz@nrubsig.org set -o errexit 188*10898Sroland.mainz@nrubsig.org 189*10898Sroland.mainz@nrubsig.org mkfifo "${_.ssl.fifo.in}" "${_.ssl.fifo.out}" 190*10898Sroland.mainz@nrubsig.org 191*10898Sroland.mainz@nrubsig.org # create async openssl child to handle https 192*10898Sroland.mainz@nrubsig.org openssl s_client -quiet -connect "${_.host}:${_.port}" <"${_.ssl.fifo.in}" >>"${_.ssl.fifo.out}" & 193*10898Sroland.mainz@nrubsig.org 194*10898Sroland.mainz@nrubsig.org _.ssl.openssl_client_pid=$! 195*10898Sroland.mainz@nrubsig.org else 196*10898Sroland.mainz@nrubsig.org redirect {_.netfd.in}<> "/dev/tcp/${_.host}/${_.port}" 197*10898Sroland.mainz@nrubsig.org (( $? != 0 )) && { print -u2 -f "%s: Could not open %s\n" "$0" "${1}" ; return 1 ; } 198*10898Sroland.mainz@nrubsig.org (( _.netfd.out=_.netfd.in )) 199*10898Sroland.mainz@nrubsig.org fi 200*10898Sroland.mainz@nrubsig.org return 0 201*10898Sroland.mainz@nrubsig.org } 2028462SApril.Chin@Sun.COM 203*10898Sroland.mainz@nrubsig.org function send_request 204*10898Sroland.mainz@nrubsig.org { 205*10898Sroland.mainz@nrubsig.org typeset request="$1" 206*10898Sroland.mainz@nrubsig.org 207*10898Sroland.mainz@nrubsig.org set -o errexit 208*10898Sroland.mainz@nrubsig.org 209*10898Sroland.mainz@nrubsig.org if [[ "${_.protocol}" == "https" ]] ; then 210*10898Sroland.mainz@nrubsig.org print -n -- "${request}\r\n" >> "${_.ssl.fifo.in}" 211*10898Sroland.mainz@nrubsig.org 212*10898Sroland.mainz@nrubsig.org redirect {_.netfd.in}< "${_.ssl.fifo.out}" 213*10898Sroland.mainz@nrubsig.org else 214*10898Sroland.mainz@nrubsig.org print -n -- "${request}\r\n" >&${_.netfd.out} 215*10898Sroland.mainz@nrubsig.org fi 216*10898Sroland.mainz@nrubsig.org return 0 217*10898Sroland.mainz@nrubsig.org } 218*10898Sroland.mainz@nrubsig.org 219*10898Sroland.mainz@nrubsig.org function cat_url 220*10898Sroland.mainz@nrubsig.org { 221*10898Sroland.mainz@nrubsig.org if [[ "${_.protocol}" == "file" ]] ; then 222*10898Sroland.mainz@nrubsig.org cat "${_.path1}" 223*10898Sroland.mainz@nrubsig.org return $? 224*10898Sroland.mainz@nrubsig.org elif [[ "${_.protocol}" == ~(Elr)http(|s) ]] ; then 225*10898Sroland.mainz@nrubsig.org compound httpresponse # http response 2268462SApril.Chin@Sun.COM 227*10898Sroland.mainz@nrubsig.org # If URL did not contain a port number in the host part then look at the 228*10898Sroland.mainz@nrubsig.org # protocol to get the port number 229*10898Sroland.mainz@nrubsig.org if [[ "${_.port}" == "${_.host}" ]] ; then 230*10898Sroland.mainz@nrubsig.org case "${_.protocol}" in 231*10898Sroland.mainz@nrubsig.org "http") _.port=80 ;; 232*10898Sroland.mainz@nrubsig.org "https") _.port=443 ;; 233*10898Sroland.mainz@nrubsig.org *) _.port="$(getent services "${_.protocol}" | sed 's/[^0-9]*//;s/\/.*//')" ;; 234*10898Sroland.mainz@nrubsig.org esac 235*10898Sroland.mainz@nrubsig.org else 236*10898Sroland.mainz@nrubsig.org _.host="${_.host%:*}" 237*10898Sroland.mainz@nrubsig.org fi 238*10898Sroland.mainz@nrubsig.org 239*10898Sroland.mainz@nrubsig.org printmsg "protocol=${_.protocol} port=${_.port} host=${_.host} path=${_.path}" 240*10898Sroland.mainz@nrubsig.org 241*10898Sroland.mainz@nrubsig.org # prechecks 242*10898Sroland.mainz@nrubsig.org [[ "${_.protocol}" != "" ]] || { print -u2 -f "%s: protocol not set.\n" "$0" ; return 1 ; } 243*10898Sroland.mainz@nrubsig.org [[ "${_.port}" != "" ]] || { print -u2 -f "%s: port not set.\n" "$0" ; return 1 ; } 244*10898Sroland.mainz@nrubsig.org [[ "${_.host}" != "" ]] || { print -u2 -f "%s: host not set.\n" "$0" ; return 1 ; } 245*10898Sroland.mainz@nrubsig.org [[ "${_.path}" != "" ]] || { print -u2 -f "%s: path not set.\n" "$0" ; return 1 ; } 246*10898Sroland.mainz@nrubsig.org 247*10898Sroland.mainz@nrubsig.org _.open_connection 2488462SApril.Chin@Sun.COM 249*10898Sroland.mainz@nrubsig.org # send HTTP request 250*10898Sroland.mainz@nrubsig.org request="GET /${_.path} HTTP/1.1\r\n" 251*10898Sroland.mainz@nrubsig.org request+="Host: ${_.host}\r\n" 252*10898Sroland.mainz@nrubsig.org request+="User-Agent: ${_.user_agent}\r\n" 253*10898Sroland.mainz@nrubsig.org request+="Connection: close\r\n" 254*10898Sroland.mainz@nrubsig.org _.send_request "${request}\r\n" 255*10898Sroland.mainz@nrubsig.org 256*10898Sroland.mainz@nrubsig.org # collect response and send it to stdout 257*10898Sroland.mainz@nrubsig.org { 258*10898Sroland.mainz@nrubsig.org _.parse_http_response httpresponse 259*10898Sroland.mainz@nrubsig.org _.cat_http_body "${httpresponse.transfer_encoding}" 260*10898Sroland.mainz@nrubsig.org } <&${_.netfd.in} 261*10898Sroland.mainz@nrubsig.org 262*10898Sroland.mainz@nrubsig.org _.close_connection 263*10898Sroland.mainz@nrubsig.org 264*10898Sroland.mainz@nrubsig.org return 0 265*10898Sroland.mainz@nrubsig.org else 266*10898Sroland.mainz@nrubsig.org return 1 267*10898Sroland.mainz@nrubsig.org fi 268*10898Sroland.mainz@nrubsig.org # notreached 269*10898Sroland.mainz@nrubsig.org } 270*10898Sroland.mainz@nrubsig.org) 2718462SApril.Chin@Sun.COM 2728462SApril.Chin@Sun.COMfunction html_entity_to_ascii 2738462SApril.Chin@Sun.COM{ 2748462SApril.Chin@Sun.COM typeset buf 2758462SApril.Chin@Sun.COM typeset entity 2768462SApril.Chin@Sun.COM typeset c 2778462SApril.Chin@Sun.COM typeset value 2788462SApril.Chin@Sun.COM 2798462SApril.Chin@Sun.COM # Todo: Add more HTML/MathML entities here 2808462SApril.Chin@Sun.COM # Note we use a static variable (typeset -S) here to make sure we 2818462SApril.Chin@Sun.COM # don't loose the cache data between calls 2828462SApril.Chin@Sun.COM typeset -S -A entity_cache=( 2838462SApril.Chin@Sun.COM # entity to ascii (fixme: add UTF-8 transliterations) 2848462SApril.Chin@Sun.COM ["nbsp"]=' ' 2858462SApril.Chin@Sun.COM ["lt"]='<' 2868462SApril.Chin@Sun.COM ["le"]='<=' 2878462SApril.Chin@Sun.COM ["gt"]='>' 2888462SApril.Chin@Sun.COM ["ge"]='>=' 2898462SApril.Chin@Sun.COM ["amp"]='&' 2908462SApril.Chin@Sun.COM ["quot"]='"' 2918462SApril.Chin@Sun.COM ["apos"]="'" 2928462SApril.Chin@Sun.COM ) 2938462SApril.Chin@Sun.COM 2948462SApril.Chin@Sun.COM buf="" 2958462SApril.Chin@Sun.COM while IFS='' read -r -N 1 c ; do 2968462SApril.Chin@Sun.COM if [[ "$c" != "&" ]] ; then 2978462SApril.Chin@Sun.COM print -n -r -- "${c}" 2988462SApril.Chin@Sun.COM continue 2998462SApril.Chin@Sun.COM fi 3008462SApril.Chin@Sun.COM 3018462SApril.Chin@Sun.COM entity="" 3028462SApril.Chin@Sun.COM while IFS='' read -r -N 1 c ; do 3038462SApril.Chin@Sun.COM case "$c" in 3048462SApril.Chin@Sun.COM ";") 3058462SApril.Chin@Sun.COM break 3068462SApril.Chin@Sun.COM ;; 3078462SApril.Chin@Sun.COM ~(Eilr)[a-z0-9#]) 3088462SApril.Chin@Sun.COM entity+="$c" 3098462SApril.Chin@Sun.COM continue 3108462SApril.Chin@Sun.COM ;; 3118462SApril.Chin@Sun.COM *) 3128462SApril.Chin@Sun.COM# debugmsg "error &${entity}${c}#" 3138462SApril.Chin@Sun.COM 3148462SApril.Chin@Sun.COM print -n -r -- "${entity}${c}" 3158462SApril.Chin@Sun.COM entity="" 3168462SApril.Chin@Sun.COM continue 2 3178462SApril.Chin@Sun.COM ;; 3188462SApril.Chin@Sun.COM esac 3198462SApril.Chin@Sun.COM done 3208462SApril.Chin@Sun.COM 3218462SApril.Chin@Sun.COM value="" 3228462SApril.Chin@Sun.COM if [[ "${entity_cache["${entity}"]}" != "" ]] ; then 3238462SApril.Chin@Sun.COM# debugmsg "match #${entity}# = #${entity_cache["${entity}"]}#" 3248462SApril.Chin@Sun.COM value="${entity_cache["${entity}"]}" 3258462SApril.Chin@Sun.COM else 3268462SApril.Chin@Sun.COM if [[ "${entity:0:1}" == "#" ]] ; then 3278462SApril.Chin@Sun.COM # decimal literal 3288462SApril.Chin@Sun.COM value="${ printf "\u[${ printf "%x" "${entity:1:8}" ; }]" ; }" 3298462SApril.Chin@Sun.COM elif [[ "${entity:0:7}" == ~(Eilr)[0-9a-f]* ]] ; then 3308462SApril.Chin@Sun.COM # hexadecimal literal 3318462SApril.Chin@Sun.COM value="${ printf "\u[${entity:0:7}]" ; }" 3328462SApril.Chin@Sun.COM else 3338462SApril.Chin@Sun.COM # unknown literal - pass-through 3348462SApril.Chin@Sun.COM value="ENT=|${entity}|" 3358462SApril.Chin@Sun.COM fi 3368462SApril.Chin@Sun.COM 3378462SApril.Chin@Sun.COM entity_cache["${entity}"]="${value}" 3388462SApril.Chin@Sun.COM 3398462SApril.Chin@Sun.COM# debugmsg "lookup #${entity}# = #${entity_cache["${entity}"]}#" 3408462SApril.Chin@Sun.COM fi 3418462SApril.Chin@Sun.COM 3428462SApril.Chin@Sun.COM printf "%s" "${value}" 3438462SApril.Chin@Sun.COM done 3448462SApril.Chin@Sun.COM 3458462SApril.Chin@Sun.COM return 0 3468462SApril.Chin@Sun.COM} 3478462SApril.Chin@Sun.COM 3488462SApril.Chin@Sun.COM# dumb xhtml handler - no CSS, tables, images, iframes or nested 3498462SApril.Chin@Sun.COM# structures are supported (and we assume that the input is correct 3508462SApril.Chin@Sun.COM# xhtml). The code was written in a trial&&error manner and should be 3518462SApril.Chin@Sun.COM# rewritten to parse xhtml correctly. 3528462SApril.Chin@Sun.COMfunction handle_html 3538462SApril.Chin@Sun.COM{ 3548462SApril.Chin@Sun.COM # we can't use global variables here when multiple callbacks use the same 3558462SApril.Chin@Sun.COM # callback function - but we can use the callback associative array for 3568462SApril.Chin@Sun.COM # variable storage instead 3578462SApril.Chin@Sun.COM nameref callbacks=${1} 3588462SApril.Chin@Sun.COM typeset tag_type="$2" 3598462SApril.Chin@Sun.COM typeset tag_value="$3" 3608462SApril.Chin@Sun.COM 3618462SApril.Chin@Sun.COM case "${tag_type}" in 3628462SApril.Chin@Sun.COM tag_begin) 3638462SApril.Chin@Sun.COM case "${tag_value}" in 3648462SApril.Chin@Sun.COM br) printf "\n" ;; 3658462SApril.Chin@Sun.COM hr) printf "\n-------------------------------------\n" ;; 3668462SApril.Chin@Sun.COM pre) callbacks["html_pre"]='true' ;; 3678462SApril.Chin@Sun.COM p) printf "\n" ;; 3688462SApril.Chin@Sun.COM esac 3698462SApril.Chin@Sun.COM ;; 3708462SApril.Chin@Sun.COM 3718462SApril.Chin@Sun.COM tag_end) 3728462SApril.Chin@Sun.COM case "${tag_value}" in 3738462SApril.Chin@Sun.COM pre) callbacks["html_pre"]='false' ;; 3748462SApril.Chin@Sun.COM esac 3758462SApril.Chin@Sun.COM ;; 3768462SApril.Chin@Sun.COM 3778462SApril.Chin@Sun.COM tag_text) 3788462SApril.Chin@Sun.COM if ${callbacks["html_pre"]} ; then 3798462SApril.Chin@Sun.COM printf "%s" "${tag_value}" 3808462SApril.Chin@Sun.COM else 3818462SApril.Chin@Sun.COM # compress spaces/newlines/tabs/etc. 3828462SApril.Chin@Sun.COM printf "%s" "${tag_value//+([\n\r\t\v[:space:][:blank:]])/ }" 3838462SApril.Chin@Sun.COM fi 3848462SApril.Chin@Sun.COM ;; 3858462SApril.Chin@Sun.COM 3868462SApril.Chin@Sun.COM document_start) 3878462SApril.Chin@Sun.COM callbacks["html_pre"]='false' 3888462SApril.Chin@Sun.COM ;; 3898462SApril.Chin@Sun.COM document_end) ;; 3908462SApril.Chin@Sun.COM esac 3918462SApril.Chin@Sun.COM 3928462SApril.Chin@Sun.COM return 0 3938462SApril.Chin@Sun.COM} 3948462SApril.Chin@Sun.COM 3958462SApril.Chin@Sun.COMfunction handle_rss 3968462SApril.Chin@Sun.COM{ 3978462SApril.Chin@Sun.COM # we can't use global variables here when multiple callbacks use the same 3988462SApril.Chin@Sun.COM # callback function - but we can use the callback associative array for 3998462SApril.Chin@Sun.COM # variable storage instead 4008462SApril.Chin@Sun.COM nameref callbacks=${1} 4018462SApril.Chin@Sun.COM typeset tag_type="$2" 4028462SApril.Chin@Sun.COM typeset tag_value="$3" 4038462SApril.Chin@Sun.COM 4048462SApril.Chin@Sun.COM case "${tag_type}" in 4058462SApril.Chin@Sun.COM tag_begin) 4068462SApril.Chin@Sun.COM case "${tag_value}" in 4078462SApril.Chin@Sun.COM item) 4088462SApril.Chin@Sun.COM item["title"]="" 4098462SApril.Chin@Sun.COM item["link"]="" 4108462SApril.Chin@Sun.COM item["tag"]="" 4118462SApril.Chin@Sun.COM item["description"]="" 4128462SApril.Chin@Sun.COM ;; 4138462SApril.Chin@Sun.COM esac 4148462SApril.Chin@Sun.COM callbacks["textbuf"]="" 4158462SApril.Chin@Sun.COM ;; 4168462SApril.Chin@Sun.COM tag_end) 4178462SApril.Chin@Sun.COM case "${tag_value}" in 4188462SApril.Chin@Sun.COM item) 4198462SApril.Chin@Sun.COM # note that each RSS item needs to be converted seperately from RSS to HTML to plain text 4208462SApril.Chin@Sun.COM # to make sure that the state of one RSS item doesn't affect others 4218462SApril.Chin@Sun.COM ( 4228462SApril.Chin@Sun.COM printf $"<br />#### RSS item: title: %s ####" "${item["title"]}" 4238462SApril.Chin@Sun.COM printf $"<br />## author: %s" "${item["author"]}" 4248462SApril.Chin@Sun.COM printf $"<br />## link: %s" "${item["link"]}" 4258462SApril.Chin@Sun.COM printf $"<br />## date: %s" "${item["pubDate"]}" 4268462SApril.Chin@Sun.COM printf $"<br />## begin description:" 4278462SApril.Chin@Sun.COM printf $"<br />%s<br />" "${item["description"]}" 4288462SApril.Chin@Sun.COM printf $"<br />## end description<br />" 4298462SApril.Chin@Sun.COM print # extra newline to make sure the sed pipeline gets flushed 4308462SApril.Chin@Sun.COM ) | 4318462SApril.Chin@Sun.COM html_entity_to_ascii | # convert XML entities (e.g. decode RSS content to HTML code) 4328462SApril.Chin@Sun.COM xml_tok "xhtmltok_cb" | # convert HTML to plain text 4338462SApril.Chin@Sun.COM html_entity_to_ascii # convert HTML entities 4348462SApril.Chin@Sun.COM ;; 4358462SApril.Chin@Sun.COM title) item["title"]="${callbacks["textbuf"]}" ; callbacks["textbuf"]="" ;; 4368462SApril.Chin@Sun.COM link) item["link"]="${callbacks["textbuf"]}" ; callbacks["textbuf"]="" ;; 4378462SApril.Chin@Sun.COM dc:creator | author) item["author"]="${callbacks["textbuf"]}" ; callbacks["textbuf"]="" ;; 4388462SApril.Chin@Sun.COM dc:date | pubDate) item["pubDate"]="${callbacks["textbuf"]}" ; callbacks["textbuf"]="" ;; 4398462SApril.Chin@Sun.COM description) item["description"]="${callbacks["textbuf"]}" ; callbacks["textbuf"]="" ;; 4408462SApril.Chin@Sun.COM esac 4418462SApril.Chin@Sun.COM callbacks["textbuf"]="" 4428462SApril.Chin@Sun.COM ;; 4438462SApril.Chin@Sun.COM tag_text) 4448462SApril.Chin@Sun.COM callbacks["textbuf"]+="${tag_value}" 4458462SApril.Chin@Sun.COM ;; 4468462SApril.Chin@Sun.COM document_start) ;; 4478462SApril.Chin@Sun.COM document_end) ;; 4488462SApril.Chin@Sun.COM esac 4498462SApril.Chin@Sun.COM return 0 4508462SApril.Chin@Sun.COM} 4518462SApril.Chin@Sun.COM 4528462SApril.Chin@Sun.COMfunction xml_tok 4538462SApril.Chin@Sun.COM{ 4548462SApril.Chin@Sun.COM typeset buf="" 4558462SApril.Chin@Sun.COM typeset namebuf="" 4568462SApril.Chin@Sun.COM typeset attrbuf="" 4578462SApril.Chin@Sun.COM typeset c="" 4588462SApril.Chin@Sun.COM typeset isendtag # bool: true/false 4598462SApril.Chin@Sun.COM typeset issingletag # bool: true/false (used for tags like "<br />") 4608462SApril.Chin@Sun.COM nameref callbacks=${1} 4618462SApril.Chin@Sun.COM 4628462SApril.Chin@Sun.COM [[ ! -z "${callbacks["document_start"]}" ]] && ${callbacks["document_start"]} "${1}" "document_start" 4638462SApril.Chin@Sun.COM 4648462SApril.Chin@Sun.COM while IFS='' read -r -N 1 c ; do 4658462SApril.Chin@Sun.COM isendtag=false 4668462SApril.Chin@Sun.COM 4678462SApril.Chin@Sun.COM if [[ "$c" == "<" ]] ; then 4688462SApril.Chin@Sun.COM # flush any text content 4698462SApril.Chin@Sun.COM if [[ "$buf" != "" ]] ; then 4708462SApril.Chin@Sun.COM [[ ! -z "${callbacks["tag_text"]}" ]] && ${callbacks["tag_text"]} "${1}" "tag_text" "$buf" 4718462SApril.Chin@Sun.COM buf="" 4728462SApril.Chin@Sun.COM fi 4738462SApril.Chin@Sun.COM 4748462SApril.Chin@Sun.COM IFS='' read -r -N 1 c 4758462SApril.Chin@Sun.COM if [[ "$c" == "/" ]] ; then 4768462SApril.Chin@Sun.COM isendtag=true 4778462SApril.Chin@Sun.COM else 4788462SApril.Chin@Sun.COM buf="$c" 4798462SApril.Chin@Sun.COM fi 4808462SApril.Chin@Sun.COM IFS='' read -r -d '>' c 4818462SApril.Chin@Sun.COM buf+="$c" 4828462SApril.Chin@Sun.COM 4838462SApril.Chin@Sun.COM # handle comments 4848462SApril.Chin@Sun.COM if [[ "$buf" == ~(El)!-- ]] ; then 4858462SApril.Chin@Sun.COM # did we read the comment completely ? 4868462SApril.Chin@Sun.COM if [[ "$buf" != ~(Elr)!--.*-- ]] ; then 4878462SApril.Chin@Sun.COM buf+=">" 4888462SApril.Chin@Sun.COM while [[ "$buf" != ~(Elr)!--.*-- ]] ; do 4898462SApril.Chin@Sun.COM IFS='' read -r -N 1 c || break 4908462SApril.Chin@Sun.COM buf+="$c" 4918462SApril.Chin@Sun.COM done 4928462SApril.Chin@Sun.COM fi 4938462SApril.Chin@Sun.COM 4948462SApril.Chin@Sun.COM [[ ! -z "${callbacks["tag_comment"]}" ]] && ${callbacks["tag_comment"]} "${1}" "tag_comment" "${buf:3:${#buf}-5}" 4958462SApril.Chin@Sun.COM buf="" 4968462SApril.Chin@Sun.COM continue 4978462SApril.Chin@Sun.COM fi 4988462SApril.Chin@Sun.COM 4998462SApril.Chin@Sun.COM # check if the tag starts and ends at the same time (like "<br />") 5008462SApril.Chin@Sun.COM if [[ "${buf}" == ~(Er).*/ ]] ; then 5018462SApril.Chin@Sun.COM issingletag=true 5028462SApril.Chin@Sun.COM buf="${buf%*/}" 5038462SApril.Chin@Sun.COM else 5048462SApril.Chin@Sun.COM issingletag=false 5058462SApril.Chin@Sun.COM fi 5068462SApril.Chin@Sun.COM 5078462SApril.Chin@Sun.COM # check if the tag has attributes (e.g. space after name) 5088462SApril.Chin@Sun.COM if [[ "$buf" == ~(E)[[:space:][:blank:]] ]] ; then 5098462SApril.Chin@Sun.COM namebuf="${buf%%~(E)[[:space:][:blank:]].*}" 5108462SApril.Chin@Sun.COM attrbuf="${buf#~(E).*[[:space:][:blank:]]}" 5118462SApril.Chin@Sun.COM else 5128462SApril.Chin@Sun.COM namebuf="$buf" 5138462SApril.Chin@Sun.COM attrbuf="" 5148462SApril.Chin@Sun.COM fi 5158462SApril.Chin@Sun.COM 5168462SApril.Chin@Sun.COM if ${isendtag} ; then 5178462SApril.Chin@Sun.COM [[ ! -z "${callbacks["tag_end"]}" ]] && ${callbacks["tag_end"]} "${1}" "tag_end" "$namebuf" 5188462SApril.Chin@Sun.COM else 5198462SApril.Chin@Sun.COM [[ ! -z "${callbacks["tag_begin"]}" ]] && ${callbacks["tag_begin"]} "${1}" "tag_begin" "$namebuf" "$attrbuf" 5208462SApril.Chin@Sun.COM 5218462SApril.Chin@Sun.COM # handle tags like <br/> (which are start- and end-tag in one piece) 5228462SApril.Chin@Sun.COM if ${issingletag} ; then 5238462SApril.Chin@Sun.COM [[ ! -z "${callbacks["tag_end"]}" ]] && ${callbacks["tag_end"]} "${1}" "tag_end" "$namebuf" 5248462SApril.Chin@Sun.COM fi 5258462SApril.Chin@Sun.COM fi 5268462SApril.Chin@Sun.COM buf="" 5278462SApril.Chin@Sun.COM else 5288462SApril.Chin@Sun.COM buf+="$c" 5298462SApril.Chin@Sun.COM fi 5308462SApril.Chin@Sun.COM done 5318462SApril.Chin@Sun.COM 5328462SApril.Chin@Sun.COM [[ ! -z "${callbacks["document_end"]}" ]] && ${callbacks["document_end"]} "${1}" "document_end" "exit_success" 5338462SApril.Chin@Sun.COM 5348462SApril.Chin@Sun.COM print # final newline to make filters like "sed" happy 5358462SApril.Chin@Sun.COM} 5368462SApril.Chin@Sun.COM 5378462SApril.Chin@Sun.COM# return the value of LC_MESSAGES needed for subprocesses which 5388462SApril.Chin@Sun.COM# want to run in a different locale/encoding 5398462SApril.Chin@Sun.COMfunction get_lc_messages 5408462SApril.Chin@Sun.COM{ 5418462SApril.Chin@Sun.COM [[ "${LC_ALL}" != "" ]] && { print "${LC_ALL}" ; return 0 ; } 5428462SApril.Chin@Sun.COM [[ "${LC_MESSAGES}" != "" ]] && { print "${LC_MESSAGES}" ; return 0 ; } 5438462SApril.Chin@Sun.COM [[ "${LANG}" != "" ]] && { print "${LANG}" ; return 0 ; } 5448462SApril.Chin@Sun.COM print "C" ; return 0 5458462SApril.Chin@Sun.COM} 5468462SApril.Chin@Sun.COM 5478462SApril.Chin@Sun.COMfunction do_rssread 5488462SApril.Chin@Sun.COM{ 5498462SApril.Chin@Sun.COM # set unicode locale since RSS is encoded in UTF-8 5508462SApril.Chin@Sun.COM # (and make sure $LC_MESSAGES is set to the parent 5518462SApril.Chin@Sun.COM # process's locale that all error messages are using 5528462SApril.Chin@Sun.COM # the callers locale/encoding) 5538462SApril.Chin@Sun.COM export \ 5548462SApril.Chin@Sun.COM LC_MESSAGES="${ get_lc_messages ; }" \ 5558462SApril.Chin@Sun.COM LC_MONETARY="en_US.UTF-8" \ 5568462SApril.Chin@Sun.COM LC_NUMERIC="en_US.UTF-8" \ 5578462SApril.Chin@Sun.COM LC_COLLATE="en_US.UTF-8" \ 5588462SApril.Chin@Sun.COM LC_CTYPE="en_US.UTF-8" \ 5598462SApril.Chin@Sun.COM LC_TIME="en_US.UTF-8" \ 5608462SApril.Chin@Sun.COM LANG="en_US.UTF-8" 5618462SApril.Chin@Sun.COM 562*10898Sroland.mainz@nrubsig.org # return non-zero exit code for this function if the rss processing below fails 563*10898Sroland.mainz@nrubsig.org set -o errexit 564*10898Sroland.mainz@nrubsig.org 565*10898Sroland.mainz@nrubsig.org urlconnection_t hc 566*10898Sroland.mainz@nrubsig.org hc.user_agent="rssread/ksh93(ssl) (2009-08-14; $(uname -s -r -p))" 567*10898Sroland.mainz@nrubsig.org hc.init_url "$1" 568*10898Sroland.mainz@nrubsig.org 569*10898Sroland.mainz@nrubsig.org # need extra newline after cat_url to terminate line with $'\n' 5708462SApril.Chin@Sun.COM # to make "xml_tok" happy 571*10898Sroland.mainz@nrubsig.org data="${ hc.cat_url ; print ; }" 572*10898Sroland.mainz@nrubsig.org 573*10898Sroland.mainz@nrubsig.org print -u2 -f "# Got %d lines of RSS data, processing...\n" "${ wc -l <<< "${data}" ; }" 574*10898Sroland.mainz@nrubsig.org 575*10898Sroland.mainz@nrubsig.org xml_tok "rsstok_cb" <<< "${data}" 576*10898Sroland.mainz@nrubsig.org 5778462SApril.Chin@Sun.COM return 0 5788462SApril.Chin@Sun.COM} 5798462SApril.Chin@Sun.COM 5808462SApril.Chin@Sun.COMfunction usage 5818462SApril.Chin@Sun.COM{ 5828462SApril.Chin@Sun.COM OPTIND=0 5838462SApril.Chin@Sun.COM getopts -a "${progname}" "${rssread_usage}" OPT '-?' 5848462SApril.Chin@Sun.COM exit 2 5858462SApril.Chin@Sun.COM} 5868462SApril.Chin@Sun.COM 5878462SApril.Chin@Sun.COM# make sure we use the ksh93 builtin versions 5888462SApril.Chin@Sun.COMbuiltin basename 5898462SApril.Chin@Sun.COMbuiltin cat 590*10898Sroland.mainz@nrubsig.orgbuiltin mkfifo 5918462SApril.Chin@Sun.COM 5928462SApril.Chin@Sun.COMtypeset -A rsstok_cb # callbacks for xml_tok 5938462SApril.Chin@Sun.COMrsstok_cb["tag_begin"]="handle_rss" 5948462SApril.Chin@Sun.COMrsstok_cb["tag_end"]="handle_rss" 5958462SApril.Chin@Sun.COMrsstok_cb["tag_text"]="handle_rss" 5968462SApril.Chin@Sun.COMrsstok_cb["textbuf"]="" 5978462SApril.Chin@Sun.COM 5988462SApril.Chin@Sun.COMtypeset -A xhtmltok_cb # callbacks for xml_tok 5998462SApril.Chin@Sun.COMxhtmltok_cb["tag_begin"]="handle_html" 6008462SApril.Chin@Sun.COMxhtmltok_cb["tag_end"]="handle_html" 6018462SApril.Chin@Sun.COMxhtmltok_cb["tag_text"]="handle_html" 6028462SApril.Chin@Sun.COMxhtmltok_cb["textbuf"]="" 6038462SApril.Chin@Sun.COMxhtmltok_cb["html_pre"]='false' 6048462SApril.Chin@Sun.COM 6058462SApril.Chin@Sun.COMtypeset -A item 6068462SApril.Chin@Sun.COM 6078462SApril.Chin@Sun.COMtypeset -A bookmark_urls 6088462SApril.Chin@Sun.COM 6098462SApril.Chin@Sun.COM# "ramdom" urls for testing 6108462SApril.Chin@Sun.COMbookmark_urls=( 6118462SApril.Chin@Sun.COM ["google_blogs_ksh"]="http://blogsearch.google.com/blogsearch_feeds?hl=en&scoring=d&q=(%22ksh93%22%7C%22ksh+93%22+%7C+%22korn93%22+%7C+%22korn+93%22)&ie=utf-8&num=100&output=rss" 6128462SApril.Chin@Sun.COM # OpenSolaris.org sites 6138462SApril.Chin@Sun.COM ["ksh93_integration"]="http://www.opensolaris.org/rss/os/project/ksh93-integration/announcements/rss2.xml" 614*10898Sroland.mainz@nrubsig.org ["ksh93_integration_ssl"]="https://www.opensolaris.org/rss/os/project/ksh93-integration/announcements/rss2.xml" 6158462SApril.Chin@Sun.COM ["shell"]="http://www.opensolaris.org/rss/os/project/shell/announcements/rss2.xml" 6168462SApril.Chin@Sun.COM ["systemz"]="http://www.opensolaris.org/rss/os/project/systemz/announcements/rss2.xml" 617*10898Sroland.mainz@nrubsig.org ["systemz_ssl"]="https://www.opensolaris.org/rss/os/project/systemz/announcements/rss2.xml" 6188462SApril.Chin@Sun.COM # some Sun staff/sites 6198462SApril.Chin@Sun.COM ["blogs_sun_com"]="http://blogs.sun.com/main/feed/entries/rss" 6208462SApril.Chin@Sun.COM ["bigadmin"]="http://www.sun.com/bigadmin/content/rss/motd.xml" 621*10898Sroland.mainz@nrubsig.org ["bigadmin_scripts"]="https://www.sun.com/bigadmin/content/rss/scripts.xml" 6228462SApril.Chin@Sun.COM ["jmcp"]="http://www.jmcp.homeunix.com/roller/jmcp/feed/entries/rss" 6238462SApril.Chin@Sun.COM ["katakai"]="http://blogs.sun.com/katakai/feed/entries/rss" 6248462SApril.Chin@Sun.COM ["alanc"]="http://blogs.sun.com/alanc/feed/entries/rss" 6258462SApril.Chin@Sun.COM ["planetsun"]="http://www.planetsun.org/rss20.xml" 6268462SApril.Chin@Sun.COM ["planetsolaris"]="http://www.planetsolaris.org/rss20.xml" 6278462SApril.Chin@Sun.COM ["planetopensolaris"]="http://planet.opensolaris.org/rss20.xml" 6288462SApril.Chin@Sun.COM ["theregister_uk"]="http://www.theregister.co.uk/headlines.rss" 6298462SApril.Chin@Sun.COM ["heise"]="http://www.heise.de/newsticker/heise.rdf" 6308462SApril.Chin@Sun.COM ["slashdot"]="http://rss.slashdot.org/Slashdot/slashdot" 631*10898Sroland.mainz@nrubsig.org ["wikipedia_command_shells"]="http://en.wikipedia.org/w/index.php?title=Comparison_of_command_shells&feed=rss&action=history" 6328462SApril.Chin@Sun.COM) 6338462SApril.Chin@Sun.COM 6348462SApril.Chin@Sun.COMtypeset progname="${ basename "${0}" ; }" 6358462SApril.Chin@Sun.COM 6368462SApril.Chin@Sun.COMtypeset -r rssread_usage=$'+ 637*10898Sroland.mainz@nrubsig.org[-?\n@(#)\$Id: rssread (Roland Mainz) 2009-08-14 \$\n] 6388462SApril.Chin@Sun.COM[-author?Roland Mainz <roland.mainz@sun.com>] 6398462SApril.Chin@Sun.COM[-author?Roland Mainz <roland.mainz@nrubsig.org>] 6408462SApril.Chin@Sun.COM[+NAME?rssread - fetch RSS messages and convert them to plain text] 6418462SApril.Chin@Sun.COM[+DESCRIPTION?\brssread\b RSS to plain text converter 6428462SApril.Chin@Sun.COM which fetches RSS streams via HTTP and converts them from 6438462SApril.Chin@Sun.COM RSS to HTML to plain text in the current locale/encoding.] 6448462SApril.Chin@Sun.COM[I:noiconv?Do not convert data from UTF-8 to current locale/encoding.] 6458462SApril.Chin@Sun.COM 6468462SApril.Chin@Sun.COM[ url ] 6478462SApril.Chin@Sun.COM 6488462SApril.Chin@Sun.COM[+SEE ALSO?\bksh93\b(1), \bshnote\b(1)] 6498462SApril.Chin@Sun.COM' 6508462SApril.Chin@Sun.COM 6518462SApril.Chin@Sun.COMtypeset noiconv=false 6528462SApril.Chin@Sun.COM 6538462SApril.Chin@Sun.COMwhile getopts -a "${progname}" "${rssread_usage}" OPT ; do 6548462SApril.Chin@Sun.COM# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 6558462SApril.Chin@Sun.COM case ${OPT} in 6568462SApril.Chin@Sun.COM I) noiconv=true ;; 6578462SApril.Chin@Sun.COM +I) noiconv=false ;; 6588462SApril.Chin@Sun.COM *) usage ;; 6598462SApril.Chin@Sun.COM esac 6608462SApril.Chin@Sun.COMdone 6618462SApril.Chin@Sun.COMshift $((OPTIND-1)) 6628462SApril.Chin@Sun.COM 6638462SApril.Chin@Sun.COMtypeset url="$1" 6648462SApril.Chin@Sun.COM 6658462SApril.Chin@Sun.COMif [[ "${url}" == "" ]] ; then 6668462SApril.Chin@Sun.COM fatal_error $"No url given." 6678462SApril.Chin@Sun.COMfi 6688462SApril.Chin@Sun.COM 6698462SApril.Chin@Sun.COMif [[ "${bookmark_urls[${url}]}" != "" ]] ; then 6708462SApril.Chin@Sun.COM printmsg $"Using bookmark ${url} = ${bookmark_urls[${url}]}" 6718462SApril.Chin@Sun.COM url="${bookmark_urls[${url}]}" 6728462SApril.Chin@Sun.COMfi 6738462SApril.Chin@Sun.COM 6748462SApril.Chin@Sun.COMif ${noiconv} ; then 6758462SApril.Chin@Sun.COM do_rssread "${url}" 6768462SApril.Chin@Sun.COMelse 6778462SApril.Chin@Sun.COM do_rssread "${url}" | iconv -f "UTF-8" - - 6788462SApril.Chin@Sun.COMfi 6798462SApril.Chin@Sun.COM 6808462SApril.Chin@Sun.COMexit 0 6818462SApril.Chin@Sun.COM#EOF. 682