Write string to virtual file?

400 Views Asked by At

Our teacher has a web server and we are allowed to test some things. I connected to the server with Putty and tried following command:

echo "i 4 r 255 g 0 b 0." > /dev/ttyACM0

ttyACM0 is a virtual file redirecting the stream to a serial interface. This specific command changes the color of a rgb led. But the same command doesn't work in php with exec or shell_exec:

<?php
    // Script saved at /home/STUDENT_NAME/public_html/blink.php
    echo shell_exec("echo \"i 4 r 255 g 0 b 0.\" > /dev/ttyACM0"); // Doesn't work
    echo shell_exec("echo \"Hello\""); // Returns "Hello"
?>

I know that exec and shell_exec aren't disabled, because the second call to shell_exec works. My next idea was to use fopen("php://memory", "a");, but I don't know how to use these wrappers. So my questions:

  • How to use these wrappers correctly? (Maybe like "php://memory/dev/ttyACM0")
  • Is there a better solution?
1

There are 1 best solutions below

4
On

When you work on the file through the web, all file accesses are performed through the user the web server is running as, which is likely different from the user you login as through PuTTY. Thus you might be encountering a permission issue. Check the permissions on the tty device:

ls -l /dev/ttyACM0

I guess it will be group-writable, so take note of the group and check if your user is part of that group:

groups

Then check if the user the HTTP server is running as has the same right:

ps aux | grep http

This should show a list of all processes containing http in their name, and the web server will likely be among them. Identify it, and the first column of the corresponding line will tell you the user the web server is using. Let's suppose it is apache. Now run:

groups apache

(Or whatever you discovered in the previous step) This will show you the groups the user belongs to, and I bet the group ttyACM0 belongs to will not be among those. You will need to ask the sysadmin to add the user to the group.

Anyway using shell_exec in that context is very bad practice. I think you can just open the serial device and write to it:

$fp = fopen ("/dev/ttyACM0", "w");
fwrite ($fp, "i 4 r 255 g 0 b 0.\n");
fclose ($fp);

Of course this won't work if the HTTP server user does not have the permission to write to the device. Also, make sure to pay attention to the line termination in the fwrite(), you might need it or not, or even need a different one (\r or \r\n);