Apache Server configuration support - Apache module in C

This is Interesting: Free IT Magazines  
Home > Archive > Apache Server configuration support > August 2006 > Apache module in C





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Apache module in C
sphere

2006-08-26, 7:54 am

Hello

I'm just getting along with the apache2 modules features and
limitations but it seems i can't find a documentation to clear some
questions of mine.
First of all, I'm trying to make a module that keeps some data
persistent in memory between requests, information that can be
retrieved lately for a specific request.[something like a connection to
something, or just a simple integer var that increments for each
request {device, db, doesn't matter} ].

And i wanted to know if it's possible to call a cgi from a module,
let's say i have computed the data in the module and i want to send it
to a cgi ?

If you can point to me some documentation would be great.

Thanks in advance

bowman

2006-08-26, 1:27 pm

sphere wrote:

> First of all, I'm trying to make a module that keeps some data
> persistent in memory between requests, information that can be
> retrieved lately for a specific request.[something like a connection to
> something, or just a simple integer var that increments for each
> request {device, db, doesn't matter} ].


You might want to look at either FastCGI or SCGI. FastCGI was an early
attempt to overcome the limitations of CGI, but didn't receive much
attention after php became popular. SCGI is the 'Simple' implementation of
the idea.

In both cases, mod_scgi or mod_fcgi is added to the Apache configuration.
Your server listens on a specified port, and Apache connects to it for
specific requests. Each request is processed separately, but the server is
persistent and can retain state information.

Ruby on Rails has renewed interest in both approaches, both to reduce the
costs of starting a new cgi process for every request, and to retain
information between requests. I've been using SCGI, which is available at
https://www.mems-exchange.org/software/scgi/ . The server in this case is
implemented in Python, but you can build and install mod_scgi by itself.

Then add a stanza to httpd.conf or elsewhere like:

LoadModule scgi_module /usr/lib64/apache2/mod_scgi.so
<Location "/scgi-bin">
SCGIServer 127.0.0.1:4000
SCGIHandler On
SetHandler scgi-handler
</Location>

A quick and dirty implementation of the C server:

========================================
=========================
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <ctype.h>


typedef struct env {
char* label;
char* value;
struct env* next;
} ENV;

static size_t read_size(int fd);
static int read_data(int fd, char* buf, size_t size);
static void free_environment(ENV* env);
static ENV* read_environment(char* buf, size_t size);
static void print_environ(int fd, ENV* environ);
static char* find_value(ENV* environ, char* label);

int main(int argc, char** argv)
{
ENV* environ = NULL;
char* buf;
int sock_fd;
int listen_fd;
int port = 4000;
size_t size;
struct sockaddr_in addr;
socklen_t addrlen;
char msgbuf[8000];
int on = 1;
int iteration = 1;
char* value;

sock_fd = socket(PF_INET, SOCK_STREAM, 0);
if (sock_fd == -1)
{
fprintf(stderr, "socket failed: %s\n", strerror(errno));
exit(-1);
}
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
memset(&addr, 0, sizeof(struct sockaddr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");

if (bind(sock_fd, (struct sockaddr*) &addr, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "bind failed: %s\n", strerror(errno));
exit(-1);
}

if (listen(sock_fd, 5) == -1)
{
fprintf(stderr, "listen failed: %s\n", strerror(errno));
exit(-1);
}
addrlen = sizeof(struct sockaddr);

while (1) {
fprintf(stderr, "listening on port %d\n", port);
listen_fd = accept(sock_fd, (struct sockaddr*) &addr, &addrlen);
if (listen_fd == -1)
{
fprintf(stderr, "accept failed: %s\n", strerror(errno));
exit(-1);
}

size = read_size(listen_fd);
fprintf(stderr, "size: %d\n", (int) size);
if (size == -1) {
goto exit;
}

buf = calloc(1, size+32);
if (buf == NULL) {
fprintf(stderr, "calloc failed: %s\n", strerror(errno));
goto exit;
}

if (read_data(listen_fd, buf, size) == -1) {
goto exit;
}

fprintf(stderr, "read the data size = %d\n", (int)size);

fprintf(stderr, "calling read_environment\n");
environ = read_environment(buf, size);


sprintf(msgbuf, "%s", "Content-Type: text/html\r\n\r\n");
write(listen_fd, msgbuf, strlen(msgbuf));
sprintf(buf, "<html><body>\r\n");
write(listen_fd, buf, strlen(buf));

value = find_value(environ, "QUERY_STRING");
sprintf(msgbuf, "iteration %d<br/>value: %s<br/>", iteration++, value);
write(listen_fd, msgbuf, strlen(msgbuf));

if (environ) {
print_environ(listen_fd, environ);
free_environment(environ);
}
else {
fprintf(stderr, "no environ\n");
sprintf(msgbuf, "Hello World from Buddha");
write(listen_fd, msgbuf, strlen(msgbuf));
}
sprintf(buf, "</body></html>\r\n");
write(listen_fd, buf, strlen(buf));
close(listen_fd);
}
exit:
close(listen_fd);
close(sock_fd);
return 0;
}

static size_t
read_size(int fd)
{
int i = 0;
char buf[32];
char c;
ssize_t bytes_read;


memset(buf, 0, sizeof buf);
while (i < sizeof(buf)-1) {
bytes_read = read(fd, &c, 1);
if (bytes_read == -1) {
fprintf(stderr, "read failed: %s\n", strerror(errno));
if (errno == EINTR || errno == EAGAIN) {
continue;
}
return -1;
}
if (c == ':') {
break;
}
if (!isdigit(c)) {
i = 0;
memset(buf, 0, sizeof buf);
}
else {
buf[i++] = c;
}
}
return (size_t) atoi(buf);
}

static int
read_data(int fd, char* buf, size_t size)
{
ssize_t bytes_read = 0;
size_t bytes_left = (size_t) size;
int index = 0;

read(fd, buf, size+31);
return 0;
while (index < size) {
bytes_read = read(fd, &buf[index], bytes_left);
if (bytes_read == -1) {
fprintf(stderr, "read failed: %s\n", strerror(errno));
if (errno == EINTR || errno == EAGAIN) {
continue;
}
return -1;
}
index += bytes_read;
bytes_left = size - bytes_read;
}
return 0;
}

static ENV*
read_environment(char* buf, size_t size)
{
ENV* node;
ENV* head = NULL;
ENV* tail = NULL;
char* label;
char* value;
char* ptr = buf;
char* end = buf + size;

while (ptr < end) {
label = strdup(ptr);
ptr += (strlen(ptr) + 1);
value = strdup(ptr);
ptr += (strlen(ptr) + 1);
node = calloc(1, sizeof(ENV));
if (node == NULL) {
fprintf(stderr, "calloc failed: %s\n", strerror(errno));
return NULL;
}
node->label = label;
node->value = value;
if (head == NULL) {
head = node;
tail = node;
}
else {
tail->next = node;
tail = node;
}
}
return head;
}

static void
free_environment(ENV* env)
{
ENV* next;
ENV* node = env;

while (node) {
next = node->next;
free(node);
node = next;
}
}

static void
print_environ(int fd, ENV* environ)
{
char buf[1024];
ENV* node;

for (node=environ; node; node=node->next) {
sprintf(buf, "%s: %s<br>", node->label, node->value);
write(fd, buf, strlen(buf));
}

}

static char*
find_value(ENV* environ, char* label)
{
ENV* node;

for (node=environ; node; node=node->next) {
if (strcasecmp(node->label, label) == 0) {
return node->value;
}
}
return "";
}







----== Posted via webservertalk.com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.webservertalk.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com