yashsingh1/xdaforums huggingface dataset:
[Magisk] HippoMan:
Follow-up ...

In the given script, the errors with "typeset" are being generated here ...

getvar() {
local VARNAME=$1
local VALUE
local PROPPATH='/data/.magisk /cache/.magisk'
[ ! -z $MAGISKTMP ] && PROPPATH="$MAGISKTMP/.magisk/config $PROPPATH"
VALUE=$(grep_prop $VARNAME $PROPPATH)
[ ! -z $VALUE ] && eval $VARNAME=\$VALUE
}

In some shells -- and the shell with which you're running this script is obviously one of them -- the "local" command is aliased to "typeset". The "local" and "typeset" commands are not 100-percent identical, although they do offer similar functionality in many cases. However, some shells do not implement "local" at all, and apparently, this shell is one which doesn't implement "local", and therefore it seems to be aliasing "local" to "typeset".

And however "typeset" happens to be implemented in this particular shell, it apparently does not do exactly the same thing that "local" was intended to do by the author of the script, and that is what's causing these particular errors.

This apparent local-to-typeset alias is what's causing the error messages to reference "typeset" instead of "local".
[Magisk] ctcx:
@HippoMan :

Thanks very much for complete explanation!

Now this finally makes sense.
[Magisk] HippoMan:
Also, I have a suggested fix for the error in the following function that I mentioned above, whose listing I repeat here ...

getvar() {
local VARNAME=$1
local VALUE
local PROPPATH='/data/.magisk /cache/.magisk'
[ ! -z $MAGISKTMP ] && PROPPATH="$MAGISKTMP/.magisk/config $PROPPATH"
VALUE=$(grep_prop $VARNAME $PROPPATH)
[ ! -z $VALUE ] && eval $VARNAME=\$VALUE
}

The purpose of "local" here is to make sure that the variables "VARNAME", "VALUE", and "PROPPATH" only have local scope within this "getvar()" function, so that if variables named "VARNAME", "VALUE", or "PROPPATH" might be also used outside of the "getvar()" functions, these local-scope values will not overrwrite any other instances of variables with the same names elsewhere during the script's execution.

But based upon the script listing that was posted earlier in this thread, I can see that neither "VARNAME", "VALUE", nor "PROPPATH" variables are used anywhere else in that script.

Therefore, the "local" keyword can safely be completely eliminated here without causing any problems with the remainder of the script's execution. This is the altered version of that function ...

getvar() {
VARNAME="$1"
PROPPATH='/data/.magisk /cache/.magisk'
[ ! -z $MAGISKTMP ] && PROPPATH="$MAGISKTMP/.magisk/config $PROPPATH"
VALUE=$(grep_prop $VARNAME $PROPPATH)
[ ! -z $VALUE ] && eval $VARNAME=\$VALUE
}

In addition to removing "local", notice that I also put double quotes around "$1" near the top, just in case the argument passed to "getvar()"" might contain embedded whitespace. Depending on how getvar() is called, some other de-references of these variables within the getvar() function might also need to be double-quoted ... but I'll leave that decision as an exercise for the reader. :)

I don't know whether any other bugs might surface after fixing this specific issue with "local". My changes are not meant to be an over-all fix for the entire script ... just a fix for this one, small issue that I noticed.

And I do not have the opportunity to debug the entire script on my own device, so I will unfortunately have to leave that (hopefully no longer onerous) task to one or more of the rest of you.

PS: In case someone wants to use the getvar() function in some other scripts that might already contain usages of variables named "VARNAME", ""VALUE", or "PROPPATH", one way to make the getvar() function a little bit safer to use (still without using "local" or "typeset") would be to do the following ...

getvar() {
__getvar_VARNAME="$1"
__getvar_PROPPATH='/data/.magisk /cache/.magisk'
[ ! -z $MAGISKTMP ] && __getvar_PROPPATH="$MAGISKTMP/.magisk/config ${__getvar_PROPPATH}"
__getvar_VALUE=$(grep_prop ${__getvar_VARNAME} ${__getvar_PROPPATH})
[ ! -z ${__getvar_VALUE} ] && eval ${__getvar_VARNAME}=\$\{__getvar_VALUE\}
}

These __getvar_-prefixed variable names still won't have local scope within the getvar() function, but the probability of finding variables named "__getvar_VARNAME", "__getvar_VALUE", and "__getvar_PROPPATH" in any other randomly chosen script that might want to use this same getvar() function is rather low.
[Magisk] ctcx:
We would need to ask TJW and/or @osm0sis what they think about this change...

AFAIU, "local" is also used as a general "convention" to just indicate that such parameters are used only within the defined function.

In the script it just coincides that those parameters are not used anywhere else; and given the explanation of the command/alias "local", in this particular case would make script more portable among devices.

Though thinking further, pndwal's error caused by all of this... is it really a "fatal" error?

Despite the error messages, pndwal's tests seemed to just go well otherwise...
[Magisk] HippoMan:
Yes, I agree that eliminating "local" might be over-kill, given that @pndwal seems to be the only person who has ever gotten this error.

But as long as he runs the script as follows, these errors with "local" and "typeset" should be totally eliminated:

/system/bin/sh /path/to/script.sh

I have tested /system/bin/sh on five Android devices, and all of these /system/bin/sh versions indeed support "local".

Deciding ***not*** to force-run this with /system/bin/sh is probably the true cause of the errors that @pndwal keeps getting.

If @pndwal is dead-set against explicitly force-running the script with /system/bin/sh, then the following wrapper script (which I'll arbitrary name as "wrapper.sh" here) could be utilized ...

exec /system/bin/sh /path/to/the/real/script.sh "${@}"

Then, he can avoid force-running with /system/bin/sh, and he can just do this instead (after an appropriate "chmod +x"):

/path/to/wrapper.sh [ args ... ]

Of course, this should not be run via sourcing.

Yet another PS:

But then again, looking more carefully at the original script, I now see that it might be the case that the local-to-typeset alias could be set up in one of these files that are sourced within the script ...

. ./util_functions.sh

. ./boot_patch.sh "$BOOTIMAGE"

. $TMPDIR/install.sh

. $MODPATH/customize.sh

If "local" is somehow aliased to "typeset" in any of these entities, then we might be out of luck. This is not likely, since others haven't run into the same problem that @pndwal has encountered. But ... ... ... without knowing what's inside of those files, we can't be sure about that hypothesis.
[Magisk] HippoMan:
Yes.

Maybe just tell TJW and @osm0sis that when at least one user runs the script, the "local" inside of the getvar() function is aliased to "typeset" for that user and all these "local" commands fail ... and show them those error messages and the pertinent comments above in order to prove the point.

Maybe one or both of them understand better how to address this issue.

... or maybe they'll just say not to run the script in the way that @pndwal is running it.

That reminds me of something:

A guy goes to the doctor ...

Doctor: "What seems to be the problem?"

Guy: "Well, doc, when I raise my arm this way, it really hurts a lot." He then raises his arm to show the doctor.

Doctor: "So don't raise your arm that way."
[Magisk] J.Michael:
I no longer understand what state you are in.

I need almost every three-word segment of

explained differently.

"rebooted the phone over the OTA Screen and not magisk."?

"root in the background is somehow installed, because I see the IOS Emojis"?

Does the app info for "MM" indicate where it came from? Is a package name mentioned?

If you open a terminal emulator window, can you type "magisk --help"?
[Magisk] J.Michael:
@HippoMan I don't think there is anything unreliable about "typeset", or "local".

I thought the error was coming from "grep_prop()", where it says "local FILES=$@", without enclosing the "$@" in quotes. Except for the part where nobody but @pndwal gets this error.

My current thinking is that it is a matter of exactly which shell is being run. And I have had no luck finding a definitive way to determine which shell is being run.
[Magisk] HippoMan:
Yes, I see what you mean about the non-double-quoted $@ .

And I agree: in that case, we still don't understand why only @pndwal is getting the errors.

Maybe certain "sh" versions automatically treat $@ as "$@" and other "sh" versions don't do that ... ???

Or maybe there is something about his run environment which leads to his invocation calling getvar(), while most other people's run environment is such that the getvar() calls are never made when they are running.

I just don't have enough time to trace through the script to try to figure that out.

And also, given the text of the error messages, it's still clear that "local" is being aliased to "typeset". But now it seems that this itself isn't causing any errors, after all.

Yes, I agree it's likely to be shell-specific. I'd be interested in whether /system/bin/sh /path/to/script.sh indeed will bypass the errors.

As for determining which shell is running, certain constructs could be run initially, and trapping any errors that occur and non-errors that succeed could at least indicate which constructs are available in the current shell. This wouldn't give us the precise shell version, but at least we could determine whether the script could even run in the first place.

Of course, we'd have to know ahead of time which constructs to test. Maybe the equivalence or non-equivalence of $@ with "$@" could be one of the things that are tested.

PS: Given the variablility of "sh" functionality and the inability of scripts to determine which shell is being utilized to run them, I'm starting to think that maybe some of these utilities shouldn't be written as shell scripts in the first place. Maybe they should be compiled C/C++ functions ... or maybe written in something like Java or Kotlin.

Of course, scripts are easier and quicker to crank out than code written in these languages, but given the variety of Android devices and OS versions, perhaps we're still better off using one or more of these other languages rather than scripts.
[Magisk] HippoMan:
I just ran the following test. It turns out that $@ and "$@" are actually equivalent under /system/bin/sh.

I wrote two scripts and uploaded them to my /sdcard/ ...

(1) noquotes.sh

echo "No-quotes version"
for i in $@
do
echo " value=${i}"
done

(2) withquotes.sh

echo "With-quotes version"
for i in "$@"
do
echo " value=${i}"
done

I then got into "adb shell" and cd'ed to /sdcard/.

Then, I did the following ...

$ /system/bin/sh ./noquotes.sh 1 2 3 4 5
No-quotes version
value=1
value=2
value=3
value=4
value=5

$ /system/bin/sh ./withquotes.sh 1 2 3 4 5
With-quotes version
value=1
value=2
value=3
value=4
value=5

I tried running it with bash, and I got the same results.

And I also tried running ...

/system/bin/sh ./noquotes.sh "1 2" 3 4 5

... and ...

/system/bin/sh ./withquotes.sh "1 2" 3 4 5

And both gave the same results as above ... in other words, both listed this, with "1" and "2" treated as separate parameters in both cases ...

value=1
value=2
value=3
value=4
value=5

So indeed it might be that @pndwal is running with a different shell that handles $@ and "$@" in a more "traditional" manner.
[Magisk] ipdev:
I know the environment makes a difference on the shell. 🙃

Even in full bash, commands are not always the same across platform.

Linux has slight differences between distro(s), add MacOS into the mix and well, you might need to change a sed syntax or use a different approach to make the command compatible across platform.

# Convert html table to a usable list. tr --delete, sed '\n' and sed '\t' did not work on MacOS.
grep -B4 '</tr>' $RAW | sed '/--/d' | tr -d '\n' | sed2 | sed3 | tr '>' '\n' | sed5 | tr '<' '\t' | sed6 | tee $OUT

edit_service_script() {
if [ "$(uname -s)" = Darwin ]; then

Android is normally compatible with the more common Linux distro(s).

Interesting about "local", I will have to look more into it.

---

If you double-quote " the variables, then the -n option should work.

getvar() {

local VARNAME=$1

local VALUE

local PROPPATH='/data/.magisk /cache/.magisk'

[ -n "$MAGISKTMP" ] && PROPPATH="$MAGISKTMP"/.magisk/config "$PROPPATH"

VALUE=$(grep_prop $VARNAME $PROPPATH)

[ -n "$VALUE" ] && eval "$VARNAME"=\"$VALUE"

}

Then again, this might be rewritten.

Magisk's temp directory is now hard set to /debug_ramdisk.

So it is possible this function will be updated?

Cheers. :cowboy:

PS.

MacOS - Darwin is BSD based.
[Magisk] HippoMan:
In case anyone wants to see how complicated this "local"/"typeset" issue actually is, check out this discussion:

https://unix.stackexchange.com/ques...rt-local-keyword-for-defining-local-variables

In some cases, "local" is indeed aliased to "typeset". In other cases, it isn't.

Of course, this probably isn't the cause of @pndwal's problem.

Maybe it's a tiny bit more likely to be the $@ versus "$@" issue. However, I tried a number of shells under linux, and all accept unquoted $@ to have the exact, same behavior as double-quoted "$@". This includes bash, ksh, sh, ash, and zsh.

But maybe that's not always the case ... ???
[Magisk] osm0sis:
ash, mksh, bash and zsh (i.e. any shell you'll see on Android) all support local within a function to indicate the variable and value stays within it, and can therefore override same-named variables from external to the function or that were exported to the environment.

If someone was running the commands outside of a function or in an unusual shell, well that's just not the intended environment for the script and it would never be run that way in Magisk. Magisk has no need to make things universally portable, though most good shells support the local convention.
[Magisk] HippoMan:
Agreed about universally portable being the goal.

But @pndwal seems to have hit some sort of situation where portability is *not* universal for him.

It seems to either be related to "local" versus "typeset", $@ versus "$@", or something else that is causing *his* shell to behave non-universally when running the script.

The error seems to be occurring somewhere in the getvar() function or the grep_prop() function.
[Magisk] osm0sis:
Check my edit, sorry, Magisk has no need to make it portable, it just needs to work in Magisk. And, local is a pretty common convention on good shells was my point. Use a better shell if it doesn't have local. 🤷‍♂️😛
[Magisk] HippoMan:
Understood.

Nonetheless, the script is behaving differently for @pndwal than for many other people.

This implies non-universality.

It's erroring out for him in either getvar() or grep_prop(), and the error messages refer to "typeset".
[Magisk] osm0sis:
But is he running it on an Android device in a busybox ash standalone shell?

`ASH_STANDALONE=1 /data/adb/magisk/busybox ash`
[Magisk] HippoMan:
I don't know.

Does anyone know?

PS: But if @pndwal's choice of shell is indeed causing the problem, and if indeed his problem will go away if he doesn't choose run his choice of shell, then my doctor joke above is a perfect explanation of his situation. :)
[Magisk] osm0sis:
That's the only way it was intended to be run. "Don't raise your arm that way!" 🤣
[Magisk] pndwal:
I think you'll need to remove it... You can't have more than one iteration of Magisk App...

You'll have these conflicts if you have another Magisk App set up in 'second space ', 'work space', 'private space', 'enterprise apps' or whatever... Guess you'll need to log in to 'Work' profile to uninstall your 'MM'...

Make sure you have only one App iteration in regular user space also as it's possible to have both full Magisk App and App hidden in stub .apk installed.

🤠 PW
[Magisk] pndwal:
I made no 'decisions' or 'choices', nor do I have any 'dead-set' position! 😜

... I just ran the script the way @badabing2003 (and later, others) asked me to...

... and I'll happily do it differently if you publish the method in a "Running Android Scripts for DUMMIES"! post. 🤪 PW
[Magisk] zgfg:
Interesting (or not). I just didn't have time to follow the saga and now it's too late to catch up

If I understand correctly you got different result from the others on your Xiaomi with A11

Since I have two X phones, A11 and A12 (also stock MIUI - Xiaomi EU doesn't matter), I can also test the script in TE but who can please give me the script and/or short additional instructions if needed
[Magisk] HippoMan:
I see. Now I understand better.

Well, I published that here three or four times already. Here it is again ...

/system/bin/sh /path/to/script.sh

Advantages of doing it this way ...

(1) You will be 100-percent certain that your script will be run by the proper, standard Android shell.

(2) It will run your script even if it's resident on a FAT filesystem such as /storage/emulated/0 .

(3) You won't even have to do a "chmod +x" on the script before you try to run it.
[Magisk] pndwal:
First requested test was:

I never ran this, but used @badabing2003's version with fixes and his method from here:

Had no problems with that one...

Next, @badabing2003 said:

This is the one that completes with some errors on my device as noted. 🙂 PW
[Magisk] pndwal:
Mmm... Seems to be the same:

:/ $ su
:/ # /system/bin/sh /data/local/tmp/test2.sh
/data/local/tmp/test2.sh[6]: typeset: /cache/.magisk: is not an identifier
/data/local/tmp/test2.sh[6]: typeset: /cache/.magisk: is not an identifier
/data/local/tmp/test2.sh[6]: typeset: /cache/.magisk: is not an identifier
/data/local/tmp/test2.sh[6]: typeset: /cache/.magisk: is not an identifier
- System-as-root, keep dm/avb-verity
- Encrypted data, keep forceencrypt
-------------------------
SYSTEM_ROOT: true
KEEPVERITY: true
KEEPFORCEENCRYPT: true
RECOVERYMODE: false
PATCHVBMETAFLAG: false
ISENCRYPTED: true
VBMETAEXIST: true
:/ #

🙃 PW
[Magisk] zgfg:
Ok, I executed the script directly from MiXPlorer and then from Terminal:

/system/bin/sh /sdcard/Download/script.sh

In both cases the same results, no error

MIUI 13 (A12(
[Magisk] pndwal:
... @HippoMan, can you give syntax example to try it this way?:

👍 PW
[Magisk] zgfg:
Then I ran on my older Xiaomi with MIUI 12.5, A11 and I get same/similar error like @pndwal
[Magisk] pndwal:
@badabing2003

Seems it is an Xiaomi MIUI 12.5.x A11.x (+ other?) anomaly then... 🙃 PW
[Magisk] zgfg:
But now instead of the stock bin sh shell (on that same my older MIUI 12.5), I executed with

busybox sh /sdcard/Download/script sh

ie, by calling the shell from BusyBox and there was no typeset error

Maybe that's the way 'how the arm was supposed to be raised' - ie, that's the BB built-in to Magisk (IMO, from @osm0sis)
[Magisk] J.Michael:
I remember reading somewhere that Wu bundled busybox with Magisk specifically to ensure he had a shell (and probably other utilities) that he could count on behaving like he expected.
[Magisk] J.Michael:
@osm0sis gave the syntax.

I'm unsure about his reverse-apostrophes. They have a specific meaning in the shell. I don't see any need for them in this test case.

You shouldn't need to use "su" to run these tests. You should be able to put test2.sh in the Downloads directory on your internal sdcard, or in the home directory ("cd ~") provided by your terminal emulator, and then just type

sh test2.sh

Did you get a chance to try any of the ways I listed to try to identify your shell?
[Magisk] pndwal:
Ah, so I see it's a simple matter of specifying busybox sh...

I can confirm this fixes issues (line spacing added for clarity):

:/ $ su

:/ # busybox sh /data/local/tmp/test2.sh

- System-as-root, keep dm/avb-verity
- Encrypted data, keep forceencrypt
-------------------------
SYSTEM_ROOT: true
KEEPVERITY: true
KEEPFORCEENCRYPT: true
RECOVERYMODE: false
PATCHVBMETAFLAG: false
ISENCRYPTED: true
VBMETAEXIST: true

:/ #

Further, from other locations:

:/ $ busybox sh /storage/emulated/0/Download/test/test2.sh

sh: can't open '/storage/emulated/0/Download/test/test2.sh': Permission denied

2|:/ $ busybox sh /storage/0850-07F8/Test/test2.sh

sh: can't open '/storage/0850-07F8/Test/test2.sh': Permission denied

2|:/ $ su

:/ # busybox sh /storage/emulated/0/Download/test/test2.sh

- System-as-root, keep dm/avb-verity
- Encrypted data, keep forceencrypt
-------------------------
SYSTEM_ROOT: true
KEEPVERITY: true
KEEPFORCEENCRYPT: true
RECOVERYMODE: false
PATCHVBMETAFLAG: false
ISENCRYPTED: true
VBMETAEXIST: true

:/ # busybox sh /storage/0850-07F8/Test/test2.sh

- System-as-root, keep dm/avb-verity
- Encrypted data, keep forceencrypt
-------------------------
SYSTEM_ROOT: true
KEEPVERITY: true
KEEPFORCEENCRYPT: true
RECOVERYMODE: false
PATCHVBMETAFLAG: false
ISENCRYPTED: true
VBMETAEXIST: true

:/ #

So still obviously need SU for this, but, combining @HippoMan's and @osm0sis's points:

Seeming advantages of doing it this way:

(1) You will be 100-percent certain that your script will be run by the proper, standard busybox shell.

(2) It will run your script even if it's resident on a FAT filesystem such as /storage/emulated/0 .

(3) You won't even have to do a "chmod +x" on the script before you try to run it.

😛 PW
[Magisk] J.Michael:
What directory are you sitting in when you try running without "su"?

What does "ls -lZ test2.sh" show?
[Magisk] osm0sis:
You guys still aren't using ASH_STANDALONE=1 which forces busybox to use its own applets above what's in the path. Either export it or specify it as a command prefix. It has to be Magisk's busybox or my SELinux busybox to have the patch required for standalone mode.

export ASH_STANDALONE=1

/data/adb/magisk/busybox ash /data/local/tmp/test2.sh

or

ASH_STANDALONE=1 /data/adb/magisk/busybox ash /data/local/tmp/test2.sh

P.S. `` (backticks) are just a lazy way to suggest a code/command block since that's what they are when used in markdown, plus if copied whole directly to a shell it just dumps it into a subshell, like $() does, and unlike "".
[Magisk] pndwal:
I see these options in settings:

Shell command line:

... Guess I could set first for busybox sh and second for directory for scripts...

Also, is this set correctly?:

Is 'ls' capital i or small el followed by ess?... And is 'lZ' capital i or small el followed by zee/zed?...

Reminds me of Two Ronnie's skit; "Got any 'O's?"...

😆 PW
[Magisk] paper88:
Thanks a lot for your help and sorry for the misunderstanding but my english is not the best :(

I removed the MM App. Then I installed the manager again but still not working. I patched the boot.img again and did a "fastboot boot patched.img". Still not working.

Then I tried the "magisk --help" command but this was also not working..

I searched for the patched image from my phone in the XDA Nothing Forum and booted this and now it works!

I don't know if my Manager never patched the image correctly or maybe if it was the hidden MM App but now its working again. Thanks alot for your help!
[Magisk] pndwal:
But did you do fastboot flash boot magiskpatched.img?

fastboot boot magiskpatched.img doesn't work on all devices, and only temporarily roots anyway... It's not mentioned in official Installation Instruction page either...

🙃 PW
[Magisk] paper88:
I tried both, the most times i first boot the image and do after a direct install over magisk. If its not working then I flash the boot img in fastboot mode. This way is working fore since few years.
[Magisk] pndwal:
Thanks!... So this seems to work!:

:/ $ su
:/ # ASHSTANDALONE=1 busybox ash /data/local/tmp/test2.sh
- System-as-root, keep dm/avb-verity
- Encrypted data, keep forceencrypt
-------------------------
SYSTEM_ROOT: true
KEEPVERITY: true
KEEPFORCEENCRYPT: true
RECOVERYMODE: false
PATCHVBMETAFLAG: false
ISENCRYPTED: true
VBMETAEXIST: true

... but is this actually working/enough?:

:/ # busybox ash /data/local/tmp/test2.sh
- System-as-root, keep dm/avb-verity
- Encrypted data, keep forceencrypt
-------------------------
SYSTEM_ROOT: true
KEEPVERITY: true
KEEPFORCEENCRYPT: true
RECOVERYMODE: false
PATCHVBMETAFLAG: false
ISENCRYPTED: true
VBMETAEXIST: true

or is ash different from standalone ash?

👍 PW