Skip to content

Instantly share code, notes, and snippets.

@adh
Created March 30, 2009 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adh/87870 to your computer and use it in GitHub Desktop.
Save adh/87870 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <gc/gc.h>
int tcp_bind(unsigned int port){
struct sockaddr_in inet_addr;
int fd;
inet_addr.sin_family=AF_INET;
inet_addr.sin_port=htons(port);
inet_addr.sin_addr.s_addr = INADDR_ANY;
fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd == -1){
perror("socket");
exit(EXIT_FAILURE);
}
if (bind(fd,(struct sockaddr*)&inet_addr,
sizeof(inet_addr))==-1){
close(fd);
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(fd, 3) == -1){
perror("bind");
exit(EXIT_FAILURE);
}
return fd;
}
static size_t scgi_read_length(FILE* stream){
size_t res = 0;
int ch;
while ((ch = fgetc(stream)) != EOF){
if (ch == ':'){
return res;
} else if (ch >= '0' && ch <= '9'){
res *= 10;
res += ch - '0';
} else {
abort(); // error
}
}
}
typedef struct buffer_t {
char* ptr;
size_t len;
} buffer_t;
buffer_t* scgi_read_netstring(FILE* stream){
size_t res;
buffer_t* bs = GC_NEW(buffer_t);
bs->len = scgi_read_length(stream);
bs->ptr = GC_MALLOC_ATOMIC(bs->len);
res = fread(bs->ptr, 1, bs->len, stream);
if (res != bs->len){
abort(); // error
}
if (fgetc(stream) != ','){
abort(); // error
}
return bs;
}
void scgi_read_headers(FILE* stream){
buffer_t* buf = scgi_read_netstring(stream);
fprintf(stream, "Status: 200 OK\r\nContent-Type: text/plain\r\n\r\n");
while (buf->len){
size_t itemlen = strlen(buf->ptr);
fprintf(stream, "[%s]\n", buf->ptr);
buf->len -= itemlen + 1;
buf->ptr += itemlen + 1;
}
}
int main(int argc, char**argv){
int server_fd = tcp_bind(1337);
int client_fd;
while ((client_fd = accept(server_fd, NULL, NULL)) != -1){
fprintf(stderr, "client_fd=%d\n", client_fd);
FILE* stream = fdopen(client_fd, "r+");
if (!stream){
perror("fdopen");
}
scgi_read_headers(stream);
fclose(stream);
}
perror("accept");
return EXIT_FAILURE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment