Bug 587428

Summary: syntax error in /etc/sysconfig/network/scripts/functions, scripting style of /etc/init.d/network
Product: [openSUSE] openSUSE 11.2 Reporter: Forgotten User eOa8ijqIvd <forgotten_eOa8ijqIvd>
Component: NetworkAssignee: Marius Tomaschewski <mt>
Status: RESOLVED INVALID QA Contact: E-mail List <qa-bugs>
Severity: Major    
Priority: P5 - None CC: marcus.husar, werner
Version: Final   
Target Milestone: ---   
Hardware: All   
OS: openSUSE 11.2   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Forgotten User eOa8ijqIvd 2010-03-11 11:17:57 UTC
User-Agent:       Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.5 (like Gecko) SUSE

It appears to me that

 /etc/sysconfig/network/scripts/functions

is not /bin/sh compatible. I'm not sure if  it is /bin/bash but would doubt it too. This in opensuse 11.2 and also opensuse 11.1, I'm not sure how it is in opensuse 11.3. 

/etc/sysconfig/network/scripts/functions 

gets sourced by 

/etc/init.d/network. 

To reproduce it. Type just type 

/bin/sh 

shell_prompt$ . /etc/sysconfig/network/scripts/functions


One gets: 

sh: /etc/sysconfig/network/scripts/functions: line 297: syntax error near unexpected token `<'
sh: /etc/sysconfig/network/scripts/functions: line 297: `       done < <(LC_ALL=POSIX ip -4 address list "$1" 2>/dev/null)'

I would say a shell-construct like 

while ..

do < <(command) 

is not allowded. 
better use

command | while ...

I think that most of network-script is working is that these functions are not used in many cases.  /bin/sh seems to immediately evaluate syntax while /bin/bash it seems not when a file gets sourced. 
A pool of computers did not start network due to this error. Then patched to the current level it started again, but the error is of nature that i can happen again. 
 
Please rethink also programming-style of 

/etc/init.d/network 

Code around line 49: 

if ! . scripts/functions 2>/dev/null; then
        echo -n "Network: file /etc/sysconfig/network/scripts/functions is missing."
        rc_failed
        rc_status -v
        rc_exit
fi

I my case scripts/functions was present, but had a syntactical error but shell-output of that error was redirected to /dev/null. The resulting message "Network: file /etc/sysconfig/network/scripts/functions is missing." was not true and misleading.


Reproducible: Always

Steps to Reproduce:
1. Type just type 

/bin/sh 

shell_prompt$ . /etc/sysconfig/network/scripts/functions

2.
3.
Actual Results:  
Currently system seems to work. But it can happen again that 
starting of network fails.


Network initialization fails easely. Depending only how /bin/sh and /bin/bash 
evaluate functions from sourced files. Quite bad programming style in some place in /etc/init.d/network makes life hard to find or give a detailed report of bug.
Comment 1 Michal Zugec 2010-03-12 08:35:23 UTC
sysconfig package -> Marius
Comment 2 Dr. Werner Fink 2010-03-12 10:28:24 UTC
AFAICS the script /etc/init.d/network is a bash script and also the
file /etc/sysconfig/network/scripts/functions is for bash usage only.

The constructs '<()' and `>()' are so called fifo's explained in the
manual page of the bash in section `Process Substitution'

       Process substitution is supported on systems that support named pipes
       (FIFOs) or the /dev/fd method of naming open  files.   It  takes  the
       form  of  <(list) or >(list).  The process list is run with its input
       or output connected to a FIFO or some file in /dev/fd.  The  name  of
       this  file  is  passed  as  an argument to the current command as the
       result of the expansion.  If the >(list) form is used, writing to the
       file  will  provide input for list.  If the <(list) form is used, the
       file passed as an argument should be read to  obtain  the  output  of
       list.

       When available, process substitution is performed simultaneously with
       parameter and variable expansion, command  substitution,  and  arith-
       metic expansion.

Please note that the construct

     a=""
     while do ... a=x;... done < <(command)
     echo $a

is able to to show the new value of $a whereas the

    a=""
    command | while do ... a=x;... done

does not. Beside this the first way of using a real fifo is
normally faster then using a normal pipe.
Comment 3 Dr. Werner Fink 2010-03-12 10:44:36 UTC
Seidemark, the construct <() or ()> can be replaced by

   mkfifo /tmp/myfifo || exit 1
   command > /tmp/xxx &
   while do ... done < /tmp/xxx
   rm -f /tmp/xxx

or to be more secure and use only program from the root fs:

  trap 'rm -f $fifo' EXIT
  fifo=$(mktemp -u fifo.XXXXXXXX) || exit 1
  mknod $fifo p || exit 1
  command >  $fifo &
  while do ... done < /tmp/xxx

the script /etc/sysconfig/network/scripts/functions could
use a switch on $0 to distinguish between `sh' and `bash'
Comment 4 Marius Tomaschewski 2010-03-12 10:59:53 UTC
Thanks Werner,
you were faster. I'm not even thinking about sh compatibility -- there
is no reason for and also IMO no reason to reinvent the wheel and use
sh-compatible code as in comment 3.

(In reply to comment #0)
> User-Agent:       Mozilla/5.0 (compatible; Konqueror/4.3; Linux) KHTML/4.3.5
> (like Gecko) SUSE
> 
> It appears to me that
> 
>  /etc/sysconfig/network/scripts/functions
> 
> is not /bin/sh compatible.

> I'm not sure if  it is /bin/bash but would doubt it too.

It _is_ bash and no, it isn't sh compatible.

All scripts in sysconfig require bash and they use #!/bin/bash at
the begin. BTW: Most of the scripts in openSUSE require bash.

I'll also not change to become sh compatible. There is no reason for
use and it would require that some features can't be used any more,
e.g. regex - it makes completely no sense to reinvent the wheel.

This special example is maybe not needed in sysconfig, but it is
possible in bash >= 3.x:

pat='^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)([?]([^#]*))?(#(.*))?'
str='https://bugzilla.novell.com/show_bug.cgi?id=587428#add_comment'
if [[ $str =~ $pat ]] ; then
  declare -i i
  for ((i=0;i<${#BASH_REMATCH[@]};i++)) ; do
    echo "[$i] ${BASH_REMATCH[$i]}"
  done
fi
[0] https://bugzilla.novell.com/show_bug.cgi?id=587428#add_comment
[1] https:
[2] https
[3] //bugzilla.novell.com
[4] bugzilla.novell.com
[5] /show_bug.cgi
[6] ?id=587428
[7] id=587428
[8] #add_comment
[9] add_comment

[...]
> I would say a shell-construct like 
> 
> while ..
> 
> do < <(command)
> 
> is not allowded. 
> better use

See "man bash", "Process Substitution". It is normal bash syntax,
that opens a fifo `<()' as normal standard input for all command
in the while loop.

> I think that most of network-script is working is that these>
> functions are not used in many cases.

Sorry, but this is nonsense.

> A pool of computers did not start network due to this error.

Then don't try to use /bin/sh when a script is using /bin/bash
at the begin.


> Please rethink also programming-style of 
> 
> /etc/init.d/network 
> 
> Code around line 49: 
> 
> if ! . scripts/functions 2>/dev/null; then
>         echo -n "Network: file /etc/sysconfig/network/scripts/functions is
> missing."
>         rc_failed
>         rc_status -v
>         rc_exit
> fi
> 
> I my case scripts/functions was present, but had a syntactical error but
> shell-output of that error was redirected to /dev/null. The resulting message
> "Network: file /etc/sysconfig/network/scripts/functions is missing." was not
> true and misleading.

Yes, the message is misleading - most of the scripts are quite old,
written by many people having different styles and could get some
some cleanup. I'll fix the above when I not forget it, but there
are more urgent things to cleanup than the above message.

And no, there is no syntax error. Every script in sysconfig verified
for correct syntax (bash -n) in every RPM build.

=> INVALID, try to use wrong shell.
Comment 5 Marius Tomaschewski 2012-01-09 17:19:13 UTC
*** Bug 739338 has been marked as a duplicate of this bug. ***