WelcomeWelcome | FAQFAQ | DownloadsDownloads | WikiWiki

Author Topic: detect if script is being sourced ,aka return exit's runing script ??  (Read 1737 times)

Offline mocore

  • Hero Member
  • *****
  • Posts: 662
  • ~.~
after reading the examples "in a script, could I have the main body folowed by its functions at the botom?" http://forum.tinycorelinux.net/index.php/topic,26125.0.html

i could add to the example a pattern i have found useful ,
only calling the main function if the script is not sourced
eg

Code: [Select]
#!/bin/bash
main() { say_hi "$1" ; say_bye "$2" ; }
say_hi() { echo "hi $1" ; }
say_bye() { echo "bye $1" ;  }

# main "$@"
 (return 0 2>/dev/null) && { sourced=1;return 0; } || { main "${@}"  ; }

however the above method  to only works in bash

it appears this is because 
Code: [Select]
(return 0 2>/dev/null) fails in busybox ash
when return is called out side of a function
it has the same effect as calling exit

 i wander if  this is the expected behavior , or some effect of implementation detail edge case?..

searching around ...
some interesting hints from
https://stackoverflow.com/questions/71084642/get-sourced-filename-in-busybox-ash#comment125659789_71084643
which mentioned /proc/$$/fd/1*

eg : adding this to sourceme example
Code: [Select]
for i in  /proc/$$/fd/1* ; do echo "$i :$(readlink $i)" ; done
after running testto with the above modifications  it appears that
in the case of sourceing from within a script
/proc/$$/fd/1[0-9] ( specifically  /proc/$$/fd/10 and /proc/$$/fd/11 in the testto example from so://q/71084642/get-sourced-filename-in-busybox-ash )
link to the sourcer and the source-ee
eg
 /proc/$$/fd/10  link's to testto
and
  /proc/$$/fd/11 link's to sourceme

however according to some of the links below
generally 'detecting if a script is being sourced' is not recommended
unlikely to work in all shells and chocked full of odd cases and exceptions to the rule

so perhaps this is less topic more  warning ...

https://stackoverflow.com/questions/49755881/get-path-of-currently-executing-shell-script-run-with-busybox

https://stackoverflow.com/questions/29832037/how-to-get-script-directory-in-posix-sh  :o

https://stackoverflow.com/questions/2683279/how-to-detect-if-a-script-is-being-sourced

Offline GNUser

  • Wiki Author
  • Hero Member
  • *****
  • Posts: 1530
Re: detect if script is being sourced ,aka return exit's runing script ??
« Reply #1 on: February 28, 2023, 09:04:08 AM »
AFAIK there is no obvious, shell-agnostic way to do this. The easy solution is to keep function libraries (files meant to be sourced, which have no shebang or main function) and scripts (which have shebang and, IMHO, should have a main function) separate.

So a trivial function library would be a file containing nothing but this (file could be called gretting-functions, for example):
Code: [Select]
say_hi() { echo "hi $1" ; }
say_bye() { echo "bye $1" ;  }

/etc/init.d/tc-functions is a real-world example of a function library. Functions that are only used by a specific script should probably be defined in that script rather than in the function library.
« Last Edit: February 28, 2023, 09:08:24 AM by GNUser »

Offline mocore

  • Hero Member
  • *****
  • Posts: 662
  • ~.~
Re: detect if script is being sourced ,aka return exit's runing script ??
« Reply #2 on: March 01, 2023, 09:17:22 AM »

when return is called out side of a function
it has the same effect as calling exit


-edit-
it dose NOT have same effect as calling exit!  :-[
but dose work differently in ash

ftr
this was what i was attempting to test with
Code: [Select]
#!/usr/bin/env -S busybox ash

set -x
this=$_;
that=$0;
q="$?"

if (return 0 2>/dev/null); then
    echo "Script was sourced. \$? = $?"
fi

for i in  /proc/$$/fd/1* ; do echo "$i :$(readlink $i)" ; done


Offline mocore

  • Hero Member
  • *****
  • Posts: 662
  • ~.~
Re: detect if script is being sourced ,aka return exit's runing script ??
« Reply #3 on: March 02, 2023, 05:43:15 AM »

with out answering the 'is_sourced' question

it occurred to me that
- an argument to run main and exit , and return for other cases
would be enough without need to test all the odd invocation cases 

Code: [Select]

main() { say_hi "$1" ; say_bye "$2" ; }
say_hi() { echo "hi $1" ; }
say_bye() { echo "bye $1" ;  }

 for argx in "${@}" ; do
  case  $argx in
   m|main) shift ; main "${@}" ; exit 0 ;;
   #s|i|'source'|import) shift  ;;
   *) shift ;; # other args
  esac
 done
 # no args
 [ $# -eq 0 ] && return 0 ;
 
::)

all though it appears functions defined in the shell via terminal 
take precedence over functions sourced from script
???