AbidingDude
Programmer
So I've gotten a start writing CGI programs in C. I've been trying to learn how to process form data, and I have a few of the basics down. I installed Abyss web server on both my Windows PC and Ubuntu laptop. I've been doing the coding on my Windows PC and then copying it over to my laptop (compiling and running on both).
I felt that I had a hang of the GET method, so I tried one with the POST method. Here's my code:
This is the version I compiled and ran in Ubuntu. However, when I was testing it out, I didn't run it as a CGI. I ran it in a terminal, and for some reason I kept getting a "SEGMENTATION FAULT (core dumped)" after it displayed the first printf. Even stranger, I found that if I ended all my printf()s with \n they would display, but I would still get segmentation faults when it got to the getenv(). I realize that running from a terminal will not have the CONTENT_LENGTH variable, but shouldn't it just return NULL instead of crashing?
Out of frustration I decided to run it as a CGI anyway, and to my surprise it worked.
Also, with the fgets() from above, on my Windows PC I originally had:
fgets(e,MAXQS,stdin);
I coded this without much thought. After all, what's the point in getting the string length if I'm not going to use it and instead use the #define value?
But this was causing another issue. In Windows, this runs just fine. The program gets fed the query string and the fgets() exits successfully. In Ubuntu, it hangs and the server times-out. I'm assuming that it hangs because it's waiting for MAXQS characters. I figured fgets() is a pretty standard function, I'm surprised it behaves differently on both systems. I would love some clarity on this!
I felt that I had a hang of the GET method, so I tried one with the POST method. Here's my code:
C:
/*CGI07.c: I kind of have the hang of the "GET" method
of input. Now I'm going to try "POST".*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXQS 1024
int main(void)
{
char *s;
char e[MAXQS];
long int len;
char *parse_qs(const char *,char *);
printf("Content-Type: text/html; charset=ISO-8859-1\n\n");
printf("<HTML><TITLE>Yay!</TITLE>");
printf("<BODY BGCOLOR=\"#4411AA\" TEXT=\"#BBBBFF\">");
printf("<CENTER><H1>Spontaneously Generated Web Page!</H1></CENTER>");
printf("<HR>");
len=atol(getenv("CONTENT_LENGTH"));
printf("len = %ld<BR>",len);
if(len==0){
printf("Error getting CONTENT_LENGTH.\n");
exit(1);
}
fgets(e,len+1,stdin);
printf("QUERY_STRING:<BR>%s<BR><BR>",e);
printf("String Length: %ld<BR>",len);
while(s=parse_qs(e," <==> "))
printf("%s<BR>",s);
printf("</BODY></HTML>\n\n");
return 0;
}
#define MAXFIELD 64
#define MAXVALUE 512
#define MAXSEP 32
char *parse_qs(const char *QS,char *sep)
{
char field[MAXFIELD];
char value[MAXVALUE];
int a,QSlen;
static char ret[MAXFIELD+MAXVALUE+MAXSEP];
static int i=0;
void decode(char []);
/*Starting off with this because this function is meant to
be called repeatedly, so it's okay to check 'i' right away.*/
QSlen=strlen(QS);
if(i>=QSlen-1){
i=0;
return NULL;
}
ret[0]='\0';/*'NULL' it out for subsequent calls.*/
/*Get field.*/
a=0;
while(QS[i]!='=')
field[a++]=QS[i++];
field[a]='\0';
decode(field);
/*Get past equals sign.*/
i++;
/*Get value.*/
a=0;
while((QS[i]!='&') && (QS[i]!='\0'))
value[a++]=QS[i++];
value[a]='\0';
decode(value);
i++;/*Get past ampersand.*/
/*In the off-chance that sep is too large...*/
if(strlen(sep)>MAXSEP)
sep[MAXSEP]='\0';
strcat(ret,field);
strcat(ret,sep);
strcat(ret,value);
return ret;
}
void decode(char buff[])
{
int w=0;
int h,mark;
char mini[3];
char *endptr;/*Only needed for strtol().*/
while(buff[w]){
switch(buff[w]){
case '%':
/*It's three friggin' characters. It's not worth a loop.*/
mini[0]=buff[w+1];
mini[1]=buff[w+2];
mini[2]='\0';
h=(int)strtol(mini,&endptr,16);
buff[w++]=h;
mark=w;/*Mark where we are in the array.*/
/*Draw-in the rest of the array.*/
while(buff[w+2]){
buff[w]=buff[w+2];
w++;
}
buff[w]='\0';
w=mark;
break;
case '+':
buff[w++]=' ';
break;
default:
w++;
break;
}
}
}
Out of frustration I decided to run it as a CGI anyway, and to my surprise it worked.
Also, with the fgets() from above, on my Windows PC I originally had:
fgets(e,MAXQS,stdin);
I coded this without much thought. After all, what's the point in getting the string length if I'm not going to use it and instead use the #define value?
But this was causing another issue. In Windows, this runs just fine. The program gets fed the query string and the fgets() exits successfully. In Ubuntu, it hangs and the server times-out. I'm assuming that it hangs because it's waiting for MAXQS characters. I figured fgets() is a pretty standard function, I'm surprised it behaves differently on both systems. I would love some clarity on this!