Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

CGI Strangeness Across Platforms

Status
Not open for further replies.

AbidingDude

Programmer
Oct 7, 2012
74
US
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:
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;
		}
	}
}
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!
 
The function [tt]getenv()[/tt] returns a NULL pointer when the environment variable isn't defined. Passing that NULL to [tt]atol()[/tt] gives you your SEGMENTATION FAULT.

 
D'oh. Thanks. I was confusing the empty string "" with NULL.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top