Seu primeiro problema é:
while validmask
do ...
Nada acontece lá - você chama sua função sem nenhum argumento. E assim, retorna false e o loop pára.
O próximo problema é que você quer executar sua função até que o retorno seja válido. Para fazer isso, você precisa usar until
. Eu consegui ignorar isso antes.
Você precisa descartar a primeira instrução if
e faça o seguinte:
until validmask "$mask"
do mask=$(get_new_value)
done
O until
loop é a negação booleana do while
. Ele será executado até que o comando executado seja verdadeiro.
Também pode ser escrito:
while ! validmask "$mask"
do mask=$(get_new_mask)
done
Você pode fazer a atribuição / teste de uma só vez:
unset mask
until validmask "${mask:=$(get_new_value)}"
do mask=
done
Outro problema é que sua função validmask
não é totalmente validada para muitos casos de borda - especialmente aqueles que incluem [*?
. Eu acho que você deveria estar usando apenas case
e esquecer todas as subdivisões e declarações de variáveis.
Apenas descarte valores inválidos:
validmask()
case "${1##*[!0-9.]*}" in
(.*|*.|*..*|*.*.*.*.*|*[!.][!.][!.][!.]*) ! :;;
(*[3-9][!.][!.]*|*2[6-9][!.]*|*25[6-9]*) ! :;;
(*.*.*.*) ;; (*) ! :;;
esac
Uma pequena demonstração:
for mask in \
0.0.0.0 \
0.0.0. \
0.0.0.1233 \
0.0.0.233 \
0.0..233 \
0.0.2.233 \
0.5555.2.233 \
0.55.2.233 \
.55.2.233 \
1.55.2.233 \
255.255.255.255 \
255.255.256.255
do validmask "$mask"
printf "%-16.16s: %.$?0s%.$((!$?*4))s\n%.d" \
"$mask" bad good "0$(($?*8))"
printf "printf's return:\t $?\n\n"
done 2>/dev/null
0.0.0.0 : good
printf's return: 0
0.0.0. : bad
printf's return: 1
0.0.0.1233 : bad
printf's return: 1
0.0.0.233 : good
printf's return: 0
0.0..233 : bad
printf's return: 1
0.0.2.233 : good
printf's return: 0
0.5555.2.233 : bad
printf's return: 1
0.55.2.233 : good
printf's return: 0
.55.2.233 : bad
printf's return: 1
1.55.2.233 : good
printf's return: 0
255.255.255.255 : good
printf's return: 0
255.255.256.255 : bad
printf's return: 1
Aqui está outra versão de validmask()
que, na minha opinião, valida as máscaras. Eu não percebi antes que as netmasks eram tão restritivas.
validmask()
case ."${1##*[!.0124589]*}". in
(*.*.*.*.*.*.*|*[!.][!.][!.][!.]*) ! :;;
(*[!.25]*.[!0]*|*.[!012]*|*0[!.]*) ! :;;
(*1[!29]*|*1?[!28]*|*98*|*.2?.*) ! :;;
(*4[!.08]*|*[.2][25][!245]*) ! :;;
(.*.*.*.*.) echo "$1";; (*) ! :;;
esac
a=-1 b=0 c=0 d=0
for o in a b c d
do while [ "$(($o+=1))" -lt 1000 ] ||
! : "$(($o=255))"
do validmask "$a.$b.$c.$d"
done; done
0.0.0.0
128.0.0.0
192.0.0.0
224.0.0.0
240.0.0.0
248.0.0.0
252.0.0.0
254.0.0.0
255.0.0.0
255.128.0.0
255.192.0.0
255.224.0.0
255.240.0.0
255.248.0.0
255.252.0.0
255.254.0.0
255.255.0.0
255.255.128.0
255.255.192.0
255.255.224.0
255.255.240.0
255.255.248.0
255.255.252.0
255.255.254.0
255.255.255.0
255.255.255.128
255.255.255.192
255.255.255.224
255.255.255.240
255.255.255.248
255.255.255.252
255.255.255.254
255.255.255.255