LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 02-03-2008, 01:41 AM   #1
yogeshm02
Member
 
Registered: Jul 2004
Location: Chandigarh, India
Distribution: SuSe 10.1
Posts: 75

Rep: Reputation: 15
Question Help needed to understand a bit of shell script


Hi

Can someone explain the following piece of code from a small shell script (in particular, the one after $): -
Code:
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
Regards
 
Old 02-03-2008, 02:32 AM   #2
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,775

Rep: Reputation: 481Reputation: 481Reputation: 481Reputation: 481Reputation: 481
The variable $@ contains all the command line arguments passed to the program or function.
 
Old 02-03-2008, 02:36 AM   #3
yogeshm02
Member
 
Registered: Jul 2004
Location: Chandigarh, India
Distribution: SuSe 10.1
Posts: 75

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by gnashley View Post
The variable $@ contains all the command line arguments passed to the program or function.
Thanks, but what does ${1+"$@"} as a whole do?
 
Old 02-03-2008, 03:29 AM   #4
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
I have not truly clear the meaning of this particular line of code, but the syntax is
Code:
${parameter+alternative_value}
which means: if parameter is set, use alternative value, else use null string. In this case if argument number 1 is set, use all the argument list. But - I repeat - I cannot figure out what it means in this context.
 
Old 02-03-2008, 05:00 AM   #5
/bin/bash
Senior Member
 
Registered: Jul 2003
Location: Indiana
Distribution: Mandrake Slackware-current QNX4.25
Posts: 1,802

Rep: Reputation: 46
Code:
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
This function is common in /etc/init.d/functions script.
The start_daemon function sometimes called daemon or startproc is responsible for starting the daemons, in this case it uses the program /sbin/start_daemon. It is passing the command line arguements ${1+"$@"} to /sbin/start_daemon. So you would pass the name of the daemon to the function, this becomes $1 and as was mentioned by gnashley $@ is the command line arguements passed to the script or function.

Example:So if you call the function like this
start_daemon
it will not work, but if you call it like this:
start_daemon cupsd --nice=0 --log=on
then this should work, you need to have at least 1 argv for it to work.

Normally return is used to pass error no's back from a function.

Last edited by /bin/bash; 02-03-2008 at 05:21 AM. Reason: Un-obfuscate my comments :P
 
Old 02-03-2008, 06:20 AM   #6
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Thanks, but I still cannot figure out why simply "$@" couldn't be used in place of ${1+"$@"}.
 
Old 02-03-2008, 07:43 AM   #7
gnashley
Amigo developer
 
Registered: Dec 2003
Location: Germany
Distribution: Slackware
Posts: 4,775

Rep: Reputation: 481Reputation: 481Reputation: 481Reputation: 481Reputation: 481
It seems to simply run /sbin/start_daemon with whatever arguments are passed. If at least one argument is given then all the arguments are passed. If no argument is given then none are passed. This would have done the same thing:
return /sbin/start_daemon "$@"
 
Old 02-03-2008, 09:44 AM   #8
yogeshm02
Member
 
Registered: Jul 2004
Location: Chandigarh, India
Distribution: SuSe 10.1
Posts: 75

Original Poster
Rep: Reputation: 15
Thanks.

Actually I'm trying to write an init script (derived from skeleton script provided by openSUSE 10.3). I'm also attaching the script.
This is the error I get while starting the service: -
Code:
Starting eSpyD /etc/init.d/eSpyD-service: line 70: return: /sbin/start_daemon: numeric argument required
failed
...and this is line 70:
Code:
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
...which is probably invoked from here:
Code:
	start_daemon $ESPYD_BIN
Oops, attaching a file seems not possible, so here is complete script (I'm not removing comments): -
Code:
#!/bin/bash
#
#     Implemented from template LSB system startup script for example 
#     service/daemon FOO
#     Copyright (C) 1995--2005  Kurt Garloff, SUSE / Novell Inc.
#          
#     This library is free software; you can redistribute it and/or modify it
#     under the terms of the GNU Lesser General Public License as published by
#     the Free Software Foundation; either version 2.1 of the License, or (at
#     your option) any later version.
#			      
#     This library is distributed in the hope that it will be useful, but
#     WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#     Lesser General Public License for more details.
#      
#     You should have received a copy of the GNU Lesser General Public
#     License along with this library; if not, write to the Free Software
#     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
#     USA.
#
# /etc/init.d/eSpyD
# 
# Note: This template uses functions rc_XXX defined in /etc/rc.status on
# UnitedLinux/SUSE/Novell based Linux distributions. However, it will work
# on other distributions as well, by using the LSB (Linux Standard Base) 
# or RH functions or by open coding the needed functions.
# Read http://www.tldp.org/HOWTO/HighQuality-Apps-HOWTO/ if you prefer not 
# to use this template.
#
# chkconfig: 345 99 00
# description: eSpyD daemon which logs network usage for eSpy
# 
### BEGIN INIT INFO
# Provides:          eSpyD
# Required-Start:    
# Should-Start:
# Required-Stop:     
# Should-Stop: 
# Default-Start:     3 4 5
# Default-Stop:      0 1 2 6
# Short-Description: eSpyD daemon which logs network usage for eSpy
# Description:       Start eSpyD to allow logging of network usage which 
#	can be monitored with eSpy.
### END INIT INFO
# 

ESPYD_BIN=/usr/local/sbin/eSpyD
test -x $ESPYD_BIN || { echo "$ESPYD_BIN not installed"; 
	if [ "$1" = "stop" ]; then exit 0;
	else exit 5; fi; }

# Shell functions sourced from /etc/rc.status:
#      rc_check         check and set local and overall rc status
#      rc_status        check and set local and overall rc status
#      rc_status -v     be verbose in local rc status and clear it afterwards
#      rc_status -v -r  ditto and clear both the local and overall rc status
#      rc_status -s     display "skipped" and exit with status 3
#      rc_status -u     display "unused" and exit with status 3
#      rc_failed        set local and overall rc status to failed
#      rc_failed <num>  set local and overall rc status to <num>
#      rc_reset         clear both the local and overall rc status
#      rc_exit          exit appropriate to overall rc status
#      rc_active        checks whether a service is activated by symlinks

# Use the SUSE rc_ init script functions;
# emulate them on LSB, RH and other systems

# Default: Assume sysvinit binaries exist
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
killproc()     { return /sbin/killproc     ${1+"$@"}; }
pidofproc()    { return /sbin/pidofproc    ${1+"$@"}; }
checkproc()    { return /sbin/checkproc    ${1+"$@"}; }
if test -e /etc/rc.status; then
    # SUSE rc script library
    . /etc/rc.status
else
    export LC_ALL=POSIX
    _cmd=$1
    declare -a _SMSG
    if test "${_cmd}" = "status"; then
	_SMSG=(running dead dead unused unknown reserved)
	_RC_UNUSED=3
    else
	_SMSG=(done failed failed missed failed skipped unused failed failed reserved)
	_RC_UNUSED=6
    fi
    if test -e /lib/lsb/init-functions; then
	# LSB    
    	. /lib/lsb/init-functions
	echo_rc()
	{
	    if test ${_RC_RV} = 0; then
		log_success_msg "  [${_SMSG[${_RC_RV}]}] "
	    else
		log_failure_msg "  [${_SMSG[${_RC_RV}]}] "
	    fi
	}
	# TODO: Add checking for lockfiles
	checkproc() { return pidofproc ${1+"$@"} >/dev/null 2>&1; }
    elif test -e /etc/init.d/functions; then
	# RHAT
	. /etc/init.d/functions
	echo_rc()
	{
	    #echo -n "  [${_SMSG[${_RC_RV}]}] "
	    if test ${_RC_RV} = 0; then
		success "  [${_SMSG[${_RC_RV}]}] "
	    else
		failure "  [${_SMSG[${_RC_RV}]}] "
	    fi
	}
	checkproc() { return status ${1+"$@"}; }
	start_daemon() { return daemon ${1+"$@"}; }
    else
	# emulate it
	echo_rc() { echo "  [${_SMSG[${_RC_RV}]}] "; }
    fi
    rc_reset() { _RC_RV=0; }
    rc_failed()
    {
	if test -z "$1"; then 
	    _RC_RV=1;
	elif test "$1" != "0"; then 
	    _RC_RV=$1; 
    	fi
	return ${_RC_RV}
    }
    rc_check()
    {
	return rc_failed $?
    }	
    rc_status()
    {
	rc_failed $?
	if test "$1" = "-r"; then _RC_RV=0; shift; fi
	if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
	if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
	if test "$1" = "-v"; then echo_rc; shift; fi
	if test "$1" = "-r"; then _RC_RV=0; shift; fi
	return ${_RC_RV}
    }
    rc_exit() { exit ${_RC_RV}; }
    rc_active() 
    {
	if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
	if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
	return 1
    }
fi

# Reset status of this service
rc_reset

# Return values acc. to LSB for all commands but status:
# 0	  - success
# 1       - generic or unspecified error
# 2       - invalid or excess argument(s)
# 3       - unimplemented feature (e.g. "reload")
# 4       - user had insufficient privileges
# 5       - program is not installed
# 6       - program is not configured
# 7       - program is not running
# 8--199  - reserved (8--99 LSB, 100--149 distrib, 150--199 appl)
# 
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signaling is not supported) are
# considered a success.

case "$1" in
    start)
	echo -n "Starting eSpyD "
	## Start daemon with startproc(8). If this fails
	## the return value is set appropriately by startproc.
	start_daemon $ESPYD_BIN

	# Remember status and be verbose
	rc_status -v
	;;
    stop)
	echo -n "Shutting down eSpyD "
	## Stop daemon with killproc(8) and if this fails
	## killproc sets the return value according to LSB.

	killproc -TERM $ESPYD_BIN

	# Remember status and be verbose
	rc_status -v
	;;
    try-restart|condrestart)
	## Do a restart only if the service was active before.
	## Note: try-restart is now part of LSB (as of 1.9).
	## RH has a similar command named condrestart.
	if test "$1" = "condrestart"; then
		echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
	fi
	$0 status
	if test $? = 0; then
		$0 restart
	else
		rc_reset	# Not running is not a failure.
	fi
	# Remember status and be quiet
	rc_status
	;;
    restart)
	## Stop the service and regardless of whether it was
	## running or not, start it again.
	$0 stop
	$0 start

	# Remember status and be quiet
	rc_status
	;;
    force-reload)
	## Signal the daemon to reload its config. Most daemons
	## do this on signal 1 (SIGHUP).
	## If it does not support it, restart the service if it
	## is running.

	echo -n "Reload service eSpyD "
	$0 try-restart
	rc_status -v
	;;
    reload)
	## Like force-reload, but if daemon does not support
	## signaling, do nothing (!)

	echo -n "Reload service eSpyD "
	rc_failed 3
	rc_status -v
	;;
    status)
	echo -n "Checking for service eSpyD "
	## Check status with checkproc(8), if process is running
	## checkproc will return with exit status 0.

	# Return value is slightly different for the status command:
	# 0 - service up and running
	# 1 - service dead, but /var/run/  pid  file exists
	# 2 - service dead, but /var/lock/ lock file exists
	# 3 - service not running (unused)
	# 4 - service status unknown :-(
	# 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.)
	
	# NOTE: checkproc returns LSB compliant status values.
	checkproc $FOO_BIN
	# NOTE: rc_status knows that we called this init script with
	# "status" option and adapts its messages accordingly.
	rc_status -v
	;;
    probe)
	# Don't do anything

	;;
    *)
	echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
	exit 1
	;;
esac
rc_exit
Do you have any idea about the reason for this error?

Thanks again,
 
Old 02-03-2008, 01:05 PM   #9
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Code:
# Default: Assume sysvinit binaries exist
start_daemon() { return /sbin/start_daemon ${1+"$@"}; }
killproc()     { return /sbin/killproc     ${1+"$@"}; }
pidofproc()    { return /sbin/pidofproc    ${1+"$@"}; }
checkproc()    { return /sbin/checkproc    ${1+"$@"}; }
This sounds like a bug to me. The return statement accepts a numeric argument not a command. You can try to simply remove return from the statements above: in this case the exit status of the last (and unique) command executed inside the function is returned.

Anyway, there is another skeleton in OpenSuSE 10.3 without this sysV init compatibility part: it is /etc/init.d/skeleton, instead of /etc/init.d/skeleton.compat. Have you tried that?
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
shell script needed pirhana Linux - General 4 12-13-2007 05:15 AM
Help me understand this shell script dwhitney67 Linux - Software 2 10-18-2007 10:02 AM
shell backup script help needed Quakeboy02 Linux - Software 4 04-26-2007 06:20 PM
understand variable type in shell script qrshat Programming 5 09-09-2006 03:12 AM
Shell Script needed urgently!!!! krudupa9 Linux - General 1 06-27-2006 01:51 PM


All times are GMT -5. The time now is 06:17 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration