I've encountered several issues with process substitution and here docs/strings in the bash and mksh shells on Android.
Process substitution in bash fails for both privileged and unprivileged users.
$ cat < <(ls)
bash: /dev/fd/62: No such file or directory
bash's man page states:
Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files.
Android lacks /dev/fd but we can resolve this issue by running the following command as su (or placing it in userinit.d to be run upon boot):
ln -s /proc/self/fd /dev/fd
This sort of process substitution is not supported in mksh, but we can get around this by using named pipes, file descriptors, and here docs/strings. Here docs/strings function well in both bash and mksh while run as root/su.
Herein lies the problem: here docs/strings fail for unprivileged users in both bash and mksh
$ cat <<< "string"
bash: cannot create temp file for here-document: Permission denied
$ cat <<< "string"
/system/bin/sh: can't create temporary file /data/local/sh5debnv.tmp: Permission denied
It is clear that the shells lacks access to a suitable /tmp folder. The shell variable TMPDIR appears to be involved.
I've temporarily modified the bashrc/mkshrc files to set TMPDIR to a world-writable directory in /data for [ $USER != root ]. This functions well when running scripts from adb/terminal but seems like a sloppy and potentially dangerous idea. Setting TMPDIR to /sdcard for instance works fine when calling scripts from 'Terminal Emulator for Android' but fails elsewhere.
I'd also like scripts to function reliably when called from unprivileged non-interactive shells (i.e. Tasker or other apps). Does anyone have any suggestions for what to set TMPDIR to, where to set it from (i.e. mkshrc/bashrc, userinit.d, or repack init.rc), or some entirely new solution?