Apache module in C

This is a discussion on Apache module in C within the Apache Web Server forums, part of the Web Server and Related Forums category; Hello I'm just getting along with the apache2 modules features and limitations but it seems i can't find ...


Go Back   Usenet Forums > Web Server and Related Forums > Apache Web Server

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 08-26-2006
sphere
 
Posts: n/a
Default Apache module in C

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

  #2 (permalink)  
Old 08-26-2006
bowman
 
Posts: n/a
Default Re: Apache module in C

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 Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 05:41 PM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0