There are lots of ways of doing this. First off, if you are a beginner with setting up webpages, I would recommend you install lighttpd instead of Apache
as it is very easy to configure.
So you would do:
sudo apt-get install lighttpd php-cgi
Then save the following as lighttpd-local.conf
################################################################################
# lighttpd-local.conf
#
# Simple config file for lighttpd without needing to install Apache or configure
# any system-wide stuff in "/etc".
#
# Allows running Perl and PHP scripts as CGI. You may need:
#
# sudo apt-get php-cgi
#
# Just start serving the current directory by running:
#
# lighttpd -f lighttpd-local.conf
#
# And access it in your browser (Safari, Chrome, Firefox) at:
#
# http://<IP_ADDRESS>:8000
#
################################################################################
# To see your PHP settings and configured modules, create a file in this
# directory called "phpinfo.php" which contains:
#
# <?php
# phpinfo();
# ?>
#
# And then in your browser, navigate to:
#
# http://<IP-ADDRESS>:8000/phpinfo.php
################################################################################
# Bind to all interfaces - wired, wifi and be accessible anywhere
server.bind = "0.0.0.0"
server.port = 8000
server.document-root = CWD
server.errorlog = CWD + "/lighttpd.error.log"
accesslog.filename = CWD + "/lighttpd.access.log"
server.breakagelog = CWD + "/lighttpd.breakage.log"
index-file.names = ( "index.php", "index.html", "index.htm", "default.htm" )
server.modules = ("mod_cgi", "mod_accesslog")
# Ensure Perl and PHP scripts are executed rather than have their contents displayed
static-file.exclude-extensions = (".pl",".php")
cgi.assign = ( ".pl" => "/usr/bin/perl",
".php" => "/usr/bin/php-cgi" )
mimetype.assign = (
".css" => "text/css",
".gif" => "image/gif",
".htm" => "text/html",
".html" => "text/html",
".jpeg" => "image/jpeg",
".jpg" => "image/jpeg",
".js" => "text/javascript",
".png" => "image/png",
".txt" => "text/plain"
)
And finally start your web server, serving the contents of the local directory:
lighttpd -f lighttpd-local.conf
Then you want to consider how your webpage will interact with your C program. Some possibilities are:
- via the filesystem
- via a messaging system
- via a database
If you want to use the filesystem, basically you make a CGI-type program that writes the variable into a file whenever the user presses a button - in the example below that file is called "setting.txt"
. Your C program then reads the variable from that file. It could either read the file every time through its main loop, or your CGI-type program could send your C program a signal (e.g. kill -HUP ) and it could have signal handler that re-reads the file.
So, you would save this as index.php
:
<?php
// If we were POSTed, save the value in file on server for C program to see
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
file_put_contents("setting.txt",$_POST['val']);
// *** MARKER ***
return;
}
?>
<html>
<head>
<title>Simple Control</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<?php
// PHP - executed on server before webpage is loaded
// Get setting from previous run to pass to Javascript
$s = file_get_contents("setting.txt");
$s = intval($s);
?>
<script type="text/javascript">
// Javascript - executed on client in browser
// Put PHP variable into Javascript global
var gblSetting=<?php echo $s; ?>;
// This function is run when webpage is loaded
$(document).ready(function() {
// Display current value on webpage
$("#idCurrent").html("Current value: " + gblSetting);
// This function is run when button is clicked
$('#idButton').click(function()
{
// Toggle the global Javascript variable
gblSetting=1-gblSetting;
// Send its new value to server to save for C program to see
// See POST code at start of this file
$.ajax({
type: 'POST',
url: 'index.php',
data:'val='+ gblSetting
})
// Update value on webpage
$("#idCurrent").html("Current value: " + gblSetting);
});
});
</script>
</head>
<body>
<p>
<div id="idCurrent">Unknown</div>
<button id="idButton">Toggle value</button>
</p>
</body>
</html>
and then navigate in your browser to:
http://<IP_ADDRESS>:8000/index.php
If you have got everything correct, it will look like this:

If you wanted to send a signal to your C program whenever the file changes, you would go to the line with *** MARKER ***
and insert a call to kill. Then set up a signal handler in your C program that handles SIGHUP
for example. Signal handler setup is described here. Here is a quick example:
#include <unistd.h>
#include <chrono>
#include <thread>
#include <csignal>
#include <iostream>
int nSignals;
void signal_handler(int signal)
{
std::signal(SIGHUP, signal_handler);
std::cout << "Got signal" << std::endl;
nSignals++;
}
int main()
{
// Install a signal handler
std::signal(SIGHUP, signal_handler);
std::cout << "Send me a signal with: kill -HUP " << (int)getpid() << std::endl;
while(nSignals<5){
std::cout << "Received " << nSignals << " of 5 signals, sleeping..." << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(5));
}
}
If you want to use a messaging program, your C program would subscribe to a messaging system (nanomsg, zeromq, mosquitto) and your CGI-type program would send a message when the user clicks a button. You would insert that code into the above file where it says *** MARKER ***
.
If you want to use a database (e.g. sqlite
is small and easy, or Redis
is small and easy), your C program would read its values from the database and your CGI-type program would write the value in the database when the user clicks a button. You would insert that code into the above file where it says *** MARKER ***
. So, if you used Redis, that code might be something like:
$redis->connect('127.0.0.1'); // port 6379 by default
...
$redis->set('value', 1);
Then in your C program, you use hiredis and code like this to retrieve the current value:
redisContext *c = redisConnect("127.0.0.1", 6379);
reply = redisCommand(c,"GET value");
printf("GET value: %s\n", reply->str);
Here is a link to a Redis-type of setup that could be adapted.