User Tools

Site Tools


user:karl:cauldron:cf_funcs_requests_sh

Bash functions to Request from the Client

This function library contains bash shell functions to send requests
and catching and processing their output.
Though it had been tested with the busybox ash shell, some functions might only work correctly in bash ( or the other way around ).

The functions use code from

These client side scripting files are suggested to be installed inside the user's “HOME/.crossfire/s/” folder,
with a shortcut link cf → to the .crossfire directory,
to do have not much typing to do in the client's commandline.

Functions are usually named _function(){ ;} , functions named _ _function and _ _ _function are alternatives to the _function.

700 lines of code without much explanations…

#!/bin/ash
 
[ "$HAVE_FUNCS_REQUESTS" ] && return 0
 
# depends :
[ "$HAVE_FUNCS_COMMON"   ] || . cf_funcs_common.sh
 
_request_stub(){
 
test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request "$@"
read -t ${TMOUT:-1} ANSWER
#Script %d %s malfunction; unimplemented request:",i+1,scripts[i].name)
 _log "$REQUEST_LOG" "_request_stub $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
__request_stub(){ # for multi-line replies
 
test "$*" || return 254
 
local lANSWER lOLD_ANSWER
unset lANSWER lOLD_ANSWER ANSWER
 
_empty_message_stream
echo request $*
while :; do
 read -t $TMOUT lANSWER
 _log "$REQUEST_LOG" "__request_stub $*:$lANSWER"
 _msg 7 "$lANSWER"
 case $lANSWER in ''|$lOLD_ANSWER|*request*end) break 1;; esac
 ANSWER="$ANSWER
$lANSWER"
lOLD_ANSWER="$lANSWER"
sleep 0.01
done
ANSWER=`echo "$ANSWER" | sed 'sI^$II'`
test "$ANSWER"
}
 
_request_player_(){
#Return the player's tag and title
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request player
read -t ${TMOUT:-1} ANSWER
#request player %d %s\n", cpl.ob->tag, cpl.title
 _log "$REQUEST_LOG" "_request_player_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_player(){
#Return the player's tag and title
 
#test "$*" || return 254
 
_empty_message_stream
 
unset TAG TITLE REST
echo request player
read -t ${TMOUT:-1} r pl TAG TITLE REST
#request player %d %s\n", cpl.ob->tag, cpl.title
 _log "$REQUEST_LOG" "_request_player $*: '$TAG' '$TITLE' '$REST'"
 _msg 7 "$TAG $TITLE $REST"
 
test "$TAG" -a "$TITLE"
}
 
_request_range_(){
#Return the type and name of the currently selected range attack
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request range
read -t ${TMOUT:-1} ANSWER
#request range %s\n",cpl.range
 _log "$REQUEST_LOG" "_request_range_:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_range(){
#Return the type and name of the currently selected range attack
 
#test "$*" || return 254
 
_empty_message_stream
 
unset RANGE REST
echo request range
read -t ${TMOUT:-1} r ra RANGE REST
#request range %s\n",cpl.range
 _log "$REQUEST_LOG" "_request_range: '$RANGE' '$REST'"
 _msg 7 "$RANGE"
 
test "$RANGE"
}
 
_request_stat_stats_(){
#Return Str,Con,Dex,Int,Wis,Pow,Cha
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request stat stats
read -t ${TMOUT:-1} ANSWER
#request stat stats %d %d %d %d %d %d %d\n",
#cpl.stats.Str,cpl.stats.Con,cpl.stats.Dex,cpl.stats.Int,cpl.stats.Wis,cpl.stats.Pow,cpl.stats.Cha
 _log "$REQUEST_LOG" "_request_stat_stats_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_stat_stats(){
#Return Str,Con,Dex,Int,Wis,Pow,Cha
 
#test "$*" || return 254
 
_empty_message_stream
 
unset STR CON DEX INT WIS POW CHA
echo request stat stats
read -t ${TMOUT:-1} r s st STR CON DEX INT WIS POW CHA
#request stat stats %d %d %d %d %d %d %d\n",
#cpl.stats.Str,cpl.stats.Con,cpl.stats.Dex,cpl.stats.Int,cpl.stats.Wis,cpl.stats.Pow,cpl.stats.Cha
 _log "$REQUEST_LOG" "_request_stat_stats $*:$STR $CON $DEX $INT $WIS $POW $CHA"
 _msg 7 "$STR $CON $DEX $INT $WIS $POW $CHA"
 
test "$STR" -a "$CON" -a "$DEX" -a "$INT" -a "$WIS" -a "$POW" -a "$CHA"
}
 
_request_stat_cmbt_(){
#Return wc,ac,dam,speed,weapon_sp
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request stat cmbt
read -t ${TMOUT:-1} ANSWER
#request stat cmbt %d %d %d %d %d\n",
#cpl.stats.wc,cpl.stats.ac,cpl.stats.dam,cpl.stats.speed,cpl.stats.weapon_sp)
 _log "$REQUEST_LOG" "_request_stat_cmbt_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_stat_cmbt(){
#Return wc,ac,dam,speed,weapon_sp
 
#test "$*" || return 254
 
_empty_message_stream
 
unset WC AC DAM SPEED WP_SPEED REST
echo request stat cmbt
read -t ${TMOUT:-1} r s c WC AC DAM SPEED WP_SPEED REST
#request stat cmbt %d %d %d %d %d\n",
#cpl.stats.wc,cpl.stats.ac,cpl.stats.dam,cpl.stats.speed,cpl.stats.weapon_sp)
 _log "$REQUEST_LOG" "_request_stat_cmbt $*:$WC $AC $DAM $SPEED $WP_SPEED $REST"
 _msg 7 "$WC $AC $DAM $SPEED $WP_SPEED $REST"
 
PL_SPEED=$SPEED
test "$WC" -a "$AC" && test "$DAM" -a "$SPEED" -a "$WP_SPEED"
}
 
_request_stat_hp_(){
#Return hp,maxhp,sp,maxsp,grace,maxgrace,food
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request stat hp
read -t ${TMOUT:-1} ANSWER
#request stat hp %d %d %d %d %d %d %d\n",
#cpl.stats.hp,cpl.stats.maxhp,cpl.stats.sp,cpl.stats.maxsp,cpl.stats.grace,cpl.stats.maxgrace,cpl.stats.food)
 _log "$REQUEST_LOG" "_request_stat_hp_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_stat_hp(){
#Return hp,maxhp,sp,maxsp,grace,maxgrace,food
 
#test "$*" || return 254
 
_empty_message_stream
 
unset HP MHP SP MSP GR MGR FOOD_LVL REST
echo request stat hp
read -t ${TMOUT:-1} r s hp HP MHP SP MSP GR MGR FOOD_LVL REST
#request stat hp %d %d %d %d %d %d %d\n",
#cpl.stats.hp,cpl.stats.maxhp,cpl.stats.sp,cpl.stats.maxsp,cpl.stats.grace,cpl.stats.maxgrace,cpl.stats.food)
 _log "$REQUEST_LOG" "_request_stat_hp $*:$HP $MHP $SP $MSP $GR $MGR $FOOD_LVL $REST"
 _msg 7 "$HP $MHP $SP $MSP $GR $MGR $FOOD_LVL $REST"
 
MAXHP=$MHP
MAXSP=$MSP
MAXGR=$MGR
test "$HP" -a "$MHP" -a "$SP" -a "$MSP" -a "$GR" -a "$MGR" -a "$FOOD_LVL"
}
 
_request_stat_xp_(){
#Return level,xp,skill-1 level,skill-1 xp,...
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request stat xp
read -t ${TMOUT:-1} ANSWER
#request stat xp %d %" FMT64 ,cpl.stats.level,cpl.stats.exp)
#for(s=0;s<MAX_SKILL;++s) {
#sprintf(buf," %d %" FMT64 ,cpl.stats.skill_level[s],cpl.stats.skill_exp[s])
 _log "$REQUEST_LOG" "_request_stat_xp_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_stat_xp(){
#Return level,xp,skill-1 level,skill-1 xp,...
 
#test "$*" || return 254
 
_empty_message_stream
 
unset LEVEL EXPERIENCE REST
echo request stat xp
read -t ${TMOUT:-1} r s xp LEVEL EXPERIENCE REST
#request stat xp %d %" FMT64 ,cpl.stats.level,cpl.stats.exp)
#for(s=0;s<MAX_SKILL;++s) {
#sprintf(buf," %d %" FMT64 ,cpl.stats.skill_level[s],cpl.stats.skill_exp[s])
 _log "$REQUEST_LOG" "_request_stat_xp $*:$LEVEL $EXPERIENCE $REST"
 _msg 7 "$LEVEL $EXPERIENCE $REST"
 
test "$LEVEL" -a "$EXPERIENCE"
}
 
_request_stat_resists_(){
#Return resistances
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request stat resists
read -t ${TMOUT:-1} ANSWER
#request stat resists"
#for(s=0;s<30;++s) {
#sprintf(buf," %d",cpl.stats.resists[s])
 _log "$REQUEST_LOG" "_request_stat_resists_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_stat_resists(){
#Return resistances
 
#test "$*" || return 254
 
_empty_message_stream
 
unset R0  R1  R2  R3  R4  R5  R6  R7  R8  R9
unset R10 R11 R12 R13 R14 R15 R16 R17 R18 R19
unset R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
unset REST
 
echo request stat resists
read -t ${TMOUT:-1} r s res R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 \
 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 \
 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29 REST
#request stat resists"
#for(s=0;s<30;++s) {
#sprintf(buf," %d",cpl.stats.resists[s])
 _log "$REQUEST_LOG" "_request_stat_resists $*:$R0 $R1 $R2 $R3 $R4 $R5 $R6 $R7 $R8 $R9"
 _log "$REQUEST_LOG" "_request_stat_resists $*:$R10 $R11 $R12 $R13 $R14 $R15 $R16 $R17 $R18 $R19"
 _log "$REQUEST_LOG" "_request_stat_resists $*:$R20 $R21 $R22 $R23 $R24 $R25 $R26 $R27 $R28 $R29 $REST"
 _msg 7 "$ANSWER"
 
test "$R0" -o "$R1" -o "$R2" -o "$R3" -o "$R4" -o "$R5" -o "$R6" -o "$R7" -o "$R8" -o "$R9" && return 0
test "$R10" -o "$R11" -o "$R12" -o "$R13" -o "$R14" -o "$R15" -o "$R16" -o "$R17" -o "$R18" -o "$R19" && return 0
test "$R20" -o "$R21" -o "$R22" -o "$R23" -o "$R24" -o "$R25" -o "$R26" -o "$R27" -o "$R28" -o "$R29"
}
 
_request_stat_paths_(){
#Return spell paths: attuned, repelled, denied.
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request stat paths
read -t ${TMOUT:-1} ANSWER
#request stat paths %d %d %d\n", cpl.stats.attuned, cpl.stats.repelled, cpl.stats.denied)
 _log "$REQUEST_LOG" "_request_stat_paths_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_stat_paths(){
#Return spell paths: attuned, repelled, denied.
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ATTUNED REPELLED DENIED REST
echo request stat paths
read -t ${TMOUT:-1} r s pa ATTUNED REPELLED DENIED REST
#request stat paths %d %d %d\n", cpl.stats.attuned, cpl.stats.repelled, cpl.stats.denied)
 _log "$REQUEST_LOG" "_request_stat_paths $*:$ATTUNED $REPELLED $DENIED $REST"
 _msg 7 "$ATTUNED $REPELLED $DENIED $REST"
 
test "$ATTUNED" -o "$REPELLED" -o "$DENIED" || true
}
 
_request_weight_(){
#Return maxweight, weight
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request weight
read -t ${TMOUT:-1} ANSWER
#request weight %d %d\n",cpl.stats.weight_limit,(int)(cpl.ob->weight*1000)
 _log "$REQUEST_LOG" "_request_weight_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_weight(){
#Return maxweight, weight
 
#test "$*" || return 254
 
_empty_message_stream
 
unset MAXWEIGHT OBJWEIGHT REST
echo request weight
read -t ${TMOUT:-1} r w MAXWEIGHT OBJWEIGHT REST
#request weight %d %d\n",cpl.stats.weight_limit,(int)(cpl.ob->weight*1000)
 _log "$REQUEST_LOG" "_request_weight $*:$MAXWEIGHT $OBJWEIGHT $REST"
 _msg 7 "$MAXWEIGHT $OBJWEIGHT $REST"
 
test "$MAXWEIGHT" -a "$OBJWEIGHT"
}
 
_request_flags_(){
#Return flags (fire, run)
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request flags
read -t ${TMOUT:-1} ANSWER
#request flags %d %d %d %d\n",cpl.stats.flags,cpl.fire_on,cpl.run_on,cpl.no_echo)
 _log "$REQUEST_LOG" "_request_flags_ $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_flags(){
#Return flags (fire, run)
 
#test "$*" || return 254
 
_empty_message_stream
 
unset FL_FLAGS FL_FIRE_ON FL_RUN_ON FL_NO_ECHO REST
echo request flags
read -t ${TMOUT:-1} r fl FL_FLAGS FL_FIRE_ON FL_RUN_ON FL_NO_ECHO REST
#request flags %d %d %d %d\n",cpl.stats.flags,cpl.fire_on,cpl.run_on,cpl.no_echo)
 _log "$REQUEST_LOG" "_request_flags $*:$FL_FLAGS FL_FIRE_ON FL_RUN_ON FL_NO_ECHO REST"
 _msg 7 "$FL_FLAGS $FL_FIRE_ON $FL_RUN_ON $FL_NO_ECHO $REST"
 
#test ##TODO: UNKNOWN
}
 
__request_items_inv(){
#Return a list of items in the inventory, one per line
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request items inv
read -t ${TMOUT:-1} ANSWER
#* flags are a bitmask:
#*   magic, cursed, damned, unpaid, locked, applied, open, was_open, inv_updated
#*    256     128     64      32       16      8       4      2         1
#flags = it->magical;
#   flags = (flags<<1)|it->cursed;
#   flags = (flags<<1)|it->damned;
#   flags = (flags<<1)|it->unpaid;
#   flags = (flags<<1)|it->locked;
#   flags = (flags<<1)|it->applied;
#   flags = (flags<<1)|it->open;
#   flags = (flags<<1)|it->was_open;
#   flags = (flags<<1)|it->inv_updated;
#   snprintf(buf, sizeof(buf), "%s%d %d %d %d %d %s\n",
#    head, it->tag, it->nrof, (int)(it->weight*1000+0.5), flags, it->type, it->d_name)
#while (it) {
# script_send_item(i,"request items inv ",it)
#request items inv end\n
 _log "$REQUEST_LOG" "_request_items_inv $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
 
_request_items_inv(){
_debug "_request_items_inv:$*"
_log   "_request_items_inv:$*"
 
INV_LIST_FILE=${INV_LIST_FILE:-"$TMP_DIR"/"$MY_BASE".$$.inv}
 
local lEMPTY_LINE=0
 
unset INVENTORY_LIST
 
echo request items inv
usleep 1000
 
while :; do
unset REPLY
 
#flags=it->magical;                      1
#   flags= (flags<<1)|it->cursed;        2
#   flags= (flags<<1)|it->damned;        4
#   flags= (flags<<1)|it->unpaid;        8
#   flags= (flags<<1)|it->locked;       16
#   flags= (flags<<1)|it->applied;      32
#   flags= (flags<<1)|it->open;         64
#   flags= (flags<<1)|it->was_open;    128
#   flags= (flags<<1)|it->inv_updated; 256
 
# sprintf(buf,"%s%d %d %f %d %d %s\n",
# head,
# it->tag,
# it->nrof,
# it->weight,
# flags,
# it->type,
# it->d_name);
read -t ${TMOUT:-1}
# 72605606 1 19 17 0 flower
_log "$INV_LIST_FILE" "_request_items_inv:$REPLY"
_debug "$REPLY"
 
case $REPLY in
'') lEMPTY_LINE=$((lEMPTY_LINE+1));
    if test $lEMPTY_LINE -ge 5; then
     _log "WARNING: Inventory has too many items to request them all!"
     _warn "Inventory has too many items to request them all!"
     break 1
    fi
 ;;
*"request items inv end"*) break 1;;
 
esac
 
INVENTORY_LIST="$INVENTORY_LIST
$REPLY"
 
usleep 1000
done
 
INVENTORY_LIST=`echo "$INVENTORY_LIST" | sed 's/request items inv end//'`
INVENTORY_LIST=`echo "$INVENTORY_LIST" | sed 's/request items inv //'`
INVENTORY_LIST=`echo "$INVENTORY_LIST" | sed 's/^$//'`
 
ANSWER="$INVENTORY_LIST"
test "$ANSWER"
#test "$INVENTORY_LIST"
}
 
 
_request_items_actv(){
#Return a list of inventory items that are active, one per line
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request items actv
read -t ${TMOUT:-1} ANSWER
#while (it) {
# if (it->applied) script_send_item(i,"request items actv ",it)
#request items actv end\n
 _log "$REQUEST_LOG" "_request_items_actv $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_items_on(){
#Return a list of items under the player, one per line
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request items on
read -t ${TMOUT:-1} ANSWER
#while (it) {
# script_send_item(i,"request items on ",it)
#request items on end\n
 _log "$REQUEST_LOG" "_request_items_on $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_items_cont(){
#Return a list of items in the open container, one per line
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request items cont
read -t ${TMOUT:-1} ANSWER
#while (it) {
# script_send_item(i,"request items cont ",it)
#request items cont end\n
 _log "$REQUEST_LOG" "_request_items_cont $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_map_pos(){
#Return the players x,y within the current map
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request map pos
read -t ${TMOUT:-1} ANSWER
#request map pos %d %d\n",pl_pos.x,pl_pos.y)
 _log "$REQUEST_LOG" "_request_map_pos $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_map_near(){
#Return the 3x3 grid of the map centered on the player
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request map near
read -t ${TMOUT:-1} ANSWER
#request map %d %d unknown\n", x, y)
#request map %d %d  %d %c %c %c %c"
#       " smooth %d %d %d heads %d %d %d tails %d %d %d\n",
#       x, y, the_map.cells[x][y].darkness,
#       the_map.cells[x][y].need_update ? 'y' : 'n',
#       the_map.cells[x][y].have_darkness ? 'y' : 'n',
#       the_map.cells[x][y].need_resmooth ? 'y' : 'n',
#       the_map.cells[x][y].cleared ? 'y' : 'n',
#       the_map.cells[x][y].smooth[0], the_map.cells[x][y].smooth[1], the_map.cells[x][y].smooth[2],
#       the_map.cells[x][y].heads[0].face, the_map.cells[x][y].heads[1].face, the_map.cells[x][y].heads[2].face,
#       the_map.cells[x][y].tails[0].face, the_map.cells[x][y].tails[1].face, the_map.cells[x][y].tails[2].face
#   )
#send_map(i,
#                           x+pl_pos.x+use_config[CONFIG_MAPWIDTH]/2-1,
#                           y+pl_pos.y+use_config[CONFIG_MAPHEIGHT]/2-1
#                       )
 _log "$REQUEST_LOG" "_request_map_near $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_map_all(){
#Return all the known map information
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request map all
read -t ${TMOUT:-1} ANSWER
#for(y=0;y<the_map.y;++y)
#              for(x=0;x<the_map.x;++x)
#                 send_map(i,x,y)
#request map end\n
 _log "$REQUEST_LOG" "_request_map_all $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_map_x_y(){
#Return the information about square x,y in the current map
 
test "$*" || return 254
test "$1" || return 253
test "$2" || return 252
 
_empty_message_stream
 
unset ANSWER
echo request map $@
read -t ${TMOUT:-1} ANSWER
#if ( !*c ) return  /* No x specified */
#if ( !*c ) return; /* No y specified */
#send_map(i,x,y)
 
 _log "$REQUEST_LOG" "_request_map_x_y $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_skills(){
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request skills
read -t ${TMOUT:-1} ANSWER
#for (s = 0; s < CS_NUM_SKILLS; s++) {
#if (skill_names[s]) {
#sprintf(buf, "request skills %d %s\n", CS_STAT_SKILLINFO + s, skill_names[s])
#request skills end\n
 _log "$REQUEST_LOG" "_request_skills $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
_request_spells(){
 
#test "$*" || return 254
 
_empty_message_stream
 
unset ANSWER
echo request spells
read -t ${TMOUT:-1} ANSWER
#for (spell = cpl.spelldata; spell; spell = spell->next) {
#sprintf(buf, "request spells %d %d %d %d %d %d %d %d %s\n",
#spell->tag, spell->level, spell->sp, spell->grace,
#spell->skill_number, spell->path, spell->time,
#spell->dam, spell->name)
#request spells end\n
 _log "$REQUEST_LOG" "_request_spells $*:$ANSWER"
 _msg 7 "$ANSWER"
 
test "$ANSWER"
}
 
###END###
HAVE_FUNCS_REQUESTS=1
user/karl/cauldron/cf_funcs_requests_sh.txt · Last modified: 2018/04/05 08:02 by karl