Documentation server
This is an example of a WWW server dedicated to serve documentation
files...
It's fast. I don't know if it is safe, but since it's only 3kb of source
code is shouldn't be so hard to make it safe.
I think that using a server gives us much more flexibility...
--
Nicolás Lichtmaier.-
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
typedef struct
{
char *ext;
char *mimetype;
} filetype;
filetype types[] =
{
{"txt","text/plain"},
{"html","text/html"},
{"htm","text/html"},
{"gif","image/gif"},
{"jpg","image/jpeg"},
{"png","image/png"},
{"ps","application/postcript"},
{NULL,NULL}
};
void error(int code, const char *msg)
{
printf("HTTP/1.0 %d Error\n"
"Content-type: text/html\n\n"
"<title>%s</title><body><h1>%s</h1></body>\n",code,msg,msg);
exit(0);
}
int valid(const char *s)
{
for(;*s & *(s+1);s++)
{
if(*s=='.' && *(s+1)=='.')
return 0;
}
return 1;
}
char *days[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
char *gettime(time_t a)
{
static char out[ 44 ];
struct tm *t;
t=gmtime(&a);
/* Format: Day, 01 Mon 1999 01:01:01 GMT */
sprintf( out, "%s, %02i %s %04i %02i:%02i:%02i GMT",
days[t->tm_wday], t->tm_mday, months[ t->tm_mon ], t->tm_year + 1900,
t->tm_hour, t->tm_min, t->tm_sec
);
return out;
}
int main()
{
char q[100],*query,fn[120],*ce=NULL;
int uncompress=0;
int t=0;
FILE *f;
query=q;
fgets(query,100,stdin);
do fgets(fn,100,stdin); while(fn[0]!='\n' && fn[0]!='\r');
if (!strncmp(query,"GET /doc",4))
{
int i;
char *p,*q;
struct stat st;
query+=4;
p=strchr(query,' ');
if(!p)
error(400,"error");
*p=0;
snprintf(fn,100,"/usr%s",query);
if (!valid(fn))
error(403,"error");
q=strrchr(fn,'/');
if (q && !*(q+1))
strcat(fn,"index.html");
p=strrchr(fn,'.');
if(p>q && !strcasecmp(p+1,"gz"))
{
ce="gzip";
if (p>fn)
{
p--;
while(p>fn && *p!='.') p--;
if (p==fn && *p!='.') p=NULL;
}
else
p=NULL;
}
if (p)
{
for (i=0;types[i].ext;i++)
if(!strcasecmp(types[i].ext,p+1))
t=i;
}
f=fopen(fn,"r");
if (!f)
{
FILE *g;
int z[2];
uncompress=1;
strcat(fn,".gz");
g=fopen(fn,"r");
if (!g)
error(404,"The requested file was not found.");
fstat(fileno(g),&st);
if (!S_ISREG(st.st_mode)) error(403,"error");
pipe(z);
if (!fork())
{
close(z[0]);
dup2(fileno(g),0);
dup2(z[1],1);
dup2(z[1],2);
execl("/bin/gzip","/bin/gzip","-dc",fn,NULL);
exit(0);
}
close(z[1]);
fclose(g);
f=fdopen(z[0],"r");
} else
{
fstat(fileno(f),&st);
if (!S_ISREG(st.st_mode)) error(403,"error");
}
printf("HTTP/1.0 200 OK\nContent-type: %s\n",types[t].mimetype);
if (ce)
printf("Content-Encoding: %s\n",ce);
if (!uncompress)
{
printf("Content-Length: %lu\n",st.st_size);
}
printf("Last-Modified: %s\n",gettime(st.st_mtime));
putchar('\n');
while(!feof(f))
{
char buf[4096];
i=fread(buf,1,4096,f);
fwrite(buf,1,i,stdout);
}
fclose(f);
return 0;
}
error(strncmp(q,"GET ",4)?405:403,"error");
return 0;
}
Reply to: