** Start of listing of h4int2.c ** /* Already done, compile the needed library: gcc -c cgis.c This yields a binary file called cgis.o which can be linked with the compiled output of a CGI C backend. */ /* This is how to build h4int2-c.cgi (whenever this sourcefile changes): Ignore this sample program: gcc -o cgiex2.cgi cgiex2.c cgis.o gcc h4int2.c cgis.o mv h4int2-c.cgi ~/Trash/ mv a.out h4int2-c.cgi */ #include #include #include #include #include #include /* Function prototype, see cgis.c: */ unsigned char *getval(unsigned char *); #define MAXCH 35 /* Deliberately small buffer to test buffer-full condition */ char* digits = "0123456789"; /* Given pointer to string, index within string of first digit, check syntax to left of that digit, must be [optionalWhite] [optionalSign]. Return empty string if OK, else return pointer to report of badness. WARNING: Some report strings are written into static array, overwritten each time this function is called, others are literals. */ char* stringIxdig1CheckBefore(char* str, int ixdig1) { #define rep1size 44 static char report[rep1size]; /* Error report will be overwritten here. */ static char* signs = "+-"; size_t ixnum1, ixsign, ixjunk1; if (0==ixdig1) return(""); /* First digit right at beginning, no problem possible. */ ixsign = strcspn(str, signs); if (ixsign < ixdig1-1) return("Sign too early, not adjacent to first digit."); if (ixsign == ixdig1-1) { ixnum1=ixsign; /* Sign where it belongs, immediately before first digit. */ } else ixnum1=ixdig1; /* No sign at all. */ ixjunk1 = strspn(str, " "); if (ixjunk1 < ixnum1) { int nch; nch = snprintf(report, rep1size, "Junk char '%c' before start of number.\n", str[ixjunk1]); if (nch >= rep1size) printf("Bug: Buffer too small: nch=%d rep1size=%d\n", nch, rep1size); return(report); } return(""); } /* Given pointer to string, index within string of first digit, check syntax to right of that digit, must be [optionalMoreDigits] [optionalWhite]. Return empty string if OK, else return pointer to report of badness. WARNING: Some report strings are written into static array, overwritten each time this function is called, others are literals. */ char* stringIxdig1CheckAfter(char* str, int ixdig1) { #define rep2size 36 static char report[rep2size]; /* Error report will be overwritten here. */ size_t ixnumzp1, ixjunk2; ixnumzp1 = ixdig1 + strspn(str+ixdig1, digits); /* End of digits, + 1 */ ixjunk2 = ixnumzp1 + strspn(str+ixnumzp1, " "); if (ixjunk2 < strlen(str)) { int nch; nch = snprintf(report, rep2size, "Junk char '%c' after end of number.", str[ixjunk2]); if (nch >= rep2size) printf("Bug: Buffer too small: nch=%d rep2size=%d\n", nch, rep2size); return(report); } return(""); } /* Given a string, check whether it consists exactly of [optional whitespace] [optional sign] one or more digits [optional whitespace], if so then return empty string, else return string saying what's wrong. WARNING: Some report strings are written into static array, overwritten each time this function is called, others are literals. */ char* stringCheckInteger(char* str) { size_t len, ixdig1; char* subrep; len = strlen(str); ixdig1 = strcspn(str, digits); if (ixdig1>=len) return("Not any digit anywhere."); subrep = stringIxdig1CheckBefore(str, ixdig1); if (strlen(subrep)>0) return(subrep); subrep = stringIxdig1CheckAfter(str, ixdig1); if (strlen(subrep)>0) return(subrep); return(""); } /* Given a string which has already been verified to contain the correct representation of an integer, i.e. [white] [sign] digits [white], check whether it can be expressed as a long long int, long int, int, short int, stop as soon as any of those fails. Tell all. */ void stringIntegerTellRange(char* str) { long long int lli; char* endptr; /* Set by strtoll */ errno = 0; lli = strtoll(str, &endptr, 10); if (ERANGE == errno) { printf("Number out of range for long long int.\n"); } else if (endptr==str) { printf("Bug: No number given.\n"); } else { long long int llix; printf("It's a valid long long int = %lld\n", lli); printf("Counting using long long ints:"); for (llix=lli; llix LONG_MAX){ printf("Too large (>%ld) for long int.\n", LONG_MAX); } else if (lli < LONG_MIN) { printf("Too far negative (<%ld) for long int.\n", LONG_MIN); } else { long int li; li = (long int)lli; printf("It's a valid long int = %ld.\n", li); if (li > INT_MAX) { printf("Too large (>%d) for int.\n", INT_MAX); } else if (li < INT_MIN) { printf("Too far negative (<%d) for int.\n", INT_MIN); } else { int i; i = (int)li; printf("It's a valid int = %d.\n", i); if (i > SHRT_MAX){ printf("Too large (>%d) for short int.\n", SHRT_MAX); } else if (i < SHRT_MIN) { printf("Too far negative (<%d) for short int.\n", SHRT_MIN); } else { short int si; si = (short int)li; printf("It's a valid short int = %d.\n", si); } } } } } void keyGetCheckIntTell(char* key) { unsigned char *val; /* Will point into temporary storage */ char* chkres; /* Will also point into temporary storage sometimes */ val = getval((unsigned char *)(key)); printf("For key [%s] the value is [%s].\n", key, val); chkres = stringCheckInteger(val); if (0 != strlen(chkres)) { printf("Bad: %s\n", chkres); } else { printf("Syntax looks good in general.\n"); stringIntegerTellRange(val); } printf("\n"); } int main(void) { printf("Content-type: text/plain\n\n"); printf("Starting to use Peter Burden's form-contents decoder:\n"); printf("**WARNING** Untested new stuff ...\n"); keyGetCheckIntTell("num1"); keyGetCheckIntTell("num2"); keyGetCheckIntTell("num3"); keyGetCheckIntTell("num4"); keyGetCheckIntTell("num5"); keyGetCheckIntTell("num6"); keyGetCheckIntTell("num7"); keyGetCheckIntTell("num8"); return(0); } ** End of listing of h4int2.c ** Here is the directory entry for that source file: -rw------- 1 rem user 6140 Feb 12 2007 h4int2.c ^ Note user execute permission *not* needed for source files. That gets compiled to a.out, but then renamed to something.cgi so that it will be usable by remote users via CGI: -rwx------ 1 rem user 10752 Feb 12 2007 h4int2-c.cgi ^ Note user execute permission needed for all CGI programs. (because compiled-C is native machine code running directly on machine)