While trying to make a webapp installation turnkey, I first added a pkg_config() function to the ebuild which in turn called the bash builtin function "read" to obtain a database name, and later on called mysql to actually create the database. This worked fine, except that vhosts can not be supported that way. I then found that webapp_hook_script() can be used to hook a shell script into the webapp-config based installation phase, and tried to implement the same functionality therein. However, in this context, "read()" will always return 1 (EACCESS?), and the same thing seems to happens to all possible workarounds (cat /dev/stdin and so on). I'm quite unsure if this is a bug or a feature. But mysql -p succeeds in accesssing the keyboard when reading the password. So why mysql succeeds? Well, because mysql implicitely uses the deprecated function "getpass" (via libmysqlclient from libc). And "getpass()" in turn reads from /dev/tty. This opens a door for a workaround: prompt_user() { exec 6<>/dev/tty read -u 6 -t 20 -p "$1" myvar \ || die "interactive read timed out after 20 seconds:$?" echo "${myvar}"; exec 6>&-; } However, I still do not get a prompt displayed. Anyway, this seems to be a sandbox issue. There is a related (now closed) bug filed by somebody who was unable to create site specific user accounts during the webapp-config phase: http://bugs.gentoo.org/show_bug.cgi?id=180799 As the argument goes, these type of scripts should not alter system wide settings. Does this also cover reading keyboard input?
Created attachment 210131 [details] emerge --info =app-admin/webapp-config-1.50.16-r3
When looking at the strace output, read(0,..) simply returns 0, no error. Using the following test program instead of builtin function read() ... #include <stdio.h> #include <errno.h> #include <string.h> int main(int argc, const char **argv) { const char *prompt = argc >1 ? argv[1] : ""; const char *dev="/dev/stdin"; FILE *fp=fopen(dev,"r"); if ( fp == NULL) { fprintf(stderr,"error opening '%s': %m\n",dev); return -errno; } fprintf(stderr,"%s",prompt); char buffer[80]; memset(buffer,0,sizeof(buffer)); if ( fscanf(fp,"%s",buffer) != EOF ) { fprintf(stdout,"%s",buffer); return 0; } fprintf(stderr,"\nerror reading '%s': %m\n",dev); return -errno; } ... leads to a similar behaviour; except that this time read(3, ...) returns 0. These lines from strace output may give an hint ... [pid 26436 is the program listed above] lstat64("/proc/26436/fd/0", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0 readlink("/proc/26436/fd/0", "pipe:[107564]"..., 4095) = 13 lstat64("/proc/26436/fd/pipe:[107564]", 0x5a471c7c) = -1 ENOENT ... to a Gentoo bug (possibly fixed with sandbox-2.2) describing a related problem: http://bugs.gentoo.org/show_bug.cgi?id=288863. However, my problem isn't at all solved by installing sandbox-2.2, even though sandbox 'echo | touch /dev/stdin' runs smoothly with the new version. Yet I now found a fully functional workaround. "read() -p prompt\>" write the prompt to stderr, which is somehow redirected in webapp-configs's context, resulting in a buffered stderr output. Consequently, redirecting additionally the output of read() to /dev/tty does the trick: prompt_user() { exec 4<>/dev/tty read -u 4 -t 20 -p "hello" myvar 2>&4 \ || die "interactive read timed out after 20 seconds: $?" exec 4>&-; echo "${myvar}"; } I'm finally setting the component to "hardened", because I currently do not know if this is problem is specific for the hardened platform only.
Devan, can you take a look at this and make a recommendation.