** Start of listing of h4int.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 h4int-c.cgi (whenever this sourcefile changes): Ignore this sample program: gcc -o cgiex2.cgi cgiex2.c cgis.o gcc h4int.c cgis.o mv h4int-c.cgi ~/Trash/ mv a.out h4int-c.cgi */ #include #include /* Function prototype, see cgis.c: */ unsigned char *getval(unsigned char *); #define maxch 10 enum errcode {nonum=-1, garbfnum=-2, signxnum=-3, garafnum=-4}; /* Given a string (nul-term), find start of number, + - or digit, pass back index by side-effect, and return 0 if OK or negative errcode: nonum = end without number, garbfnum = garbage before number */ enum errcode strchkint1(char* str, int* pix) { char ch; (*pix)=0; while (1) { ch = str[*pix]; if ((0 == ch) || ('\n' == ch)) { /* printf("At ix=%d, ch=%c, nul/eol before start.\n", *pix, ch); */ return(nonum); /* End of string without start of number */ } if (('+' == ch) || ('-' == ch)) { /* printf("At ix=%d, ch=%c, found sign.\n", *pix, ch); */ return(0); } if (('0' <= ch) && ('9' >= ch)) { /* printf("At ix=%d, ch=%c, found digit.\n", *pix, ch); */ return(0); } if (' ' == ch) (*pix)++; else { /* printf("At ix=%d, ch=%c, garbage, aborting.\n", *pix, ch); */ return(garbfnum); } } } /* Given a string (nul-term), and index where first digit or sign found, skip just the sign if that's what was found, update index, make sure a digit is immediately after the sign, return 0 if ok else error code: signxnum = sign without number */ enum errcode strchkint2(char* str, int* pix) { char ch; ch = str[*pix]; if (('+' == ch) || ('-' == ch)) { /* printf("At ix=%d, ch=%c, it was sign.\n", *pix, ch); */ (*pix)++; } ch = str[*pix]; if (('0' <= ch) && ('9' >= ch)) { /* printf("At ix=%d, ch=%c, it was digit.\n", *pix, ch); */ return(0); } /* printf("No digit after sign!\n"); */ return(signxnum); } /* Given a string (nul-term), and index where first digit found, scan to end of digits, update index, return code always 0 (OK). */ enum errcode strchkint3(char* str, int* pix) { char ch; while (1) { ch = str[*pix]; if (('0' <= ch) && ('9' >= ch)) { /* printf("At ix=%d, ch=%c, saw digit.\n", *pix, ch); */ (*pix)++; } else { /* printf("At ix=%d, ch=%c, no more digit.\n", *pix, ch); */ return(0); } } } /* Given a string (nul-term), and index where digits ended, scan to very end making sure no junk, return code: garafnum = garbage after number */ enum errcode strchkint4(char* str, int* pix) { char ch; while (1) { ch = str[*pix]; if ((0 == ch) || ('\n' == ch)) { /* printf("At ix=%d, ch=%c, nul/eol reached.\n", *pix, ch); */ return(0); } else if (' ' == ch) { /* printf("At ix=%d, ch=%c, skip white.\n", *pix, ch); */ (*pix)++; } else { /* printf("At ix=%d, ch=%c, junk.\n", *pix, ch); */ return(garafnum); } } } /* Given a string (nul-term), and integer where to put the final index, check if string consists exactly of representation of an integer (except for surrounding whitespace which are ignored). Return 0 (true) if it's all correct, an error code otherwise. Index is updated to point to EOL or NUL at end of string if all OK, else index points to first problem spot. */ enum errcode strchkint(char* str, int* pix) { enum errcode scanres; if (0 != (scanres = strchkint1(str,pix))) { /* printf("scanres#1=%d, ix=%d, aborting.\n", scanres, *pix); */ } else if (0 != (scanres = strchkint2(str,pix))) { /* printf("scanres#2=%d, ix=%d, aborting.\n", scanres, *pix); */ } else if (0 != (scanres = strchkint3(str,pix))) { /* printf("scanres#3=%d, ix=%d, aborting.\n", scanres, *pix); */ } else if (0 != (scanres = strchkint4(str,pix))) { /* printf("scanres#4=%d, ix=%d, aborting.\n", scanres, *pix); */ } else { /* printf("scanres#4=%d, ix=%d, stub.\n", scanres, *pix); */ } return(scanres); } /* Given bad results from strchkint, i.e. index where scan stopped and error code which is nonzero, describe problem to user. */ void tellproblem(char* str, int ix, enum errcode erc) { switch (erc) { case nonum: printf("Not a single digit anywhere."); break; case garbfnum: if (0==ix) { printf("Right at the very start: "); } else { printf("Everything was fine for %d characters, ",ix); printf("just whitespace, but then: "); } printf("a garbage character '%c'.",str[ix]); break; case signxnum: if (1==ix) { printf("Right at the very start: "); } else { printf("Everything was fine for %d characters, ",ix); printf("just whitespace, but then: "); } printf("sign '%c' followed non-number '%c'.", str[ix-1], str[ix]); break; case garafnum: printf("Everything was fine, optional whitespace and "); printf("sign, and good number, but then garbage character '%c'.", str[ix]); break; default: printf("(Stub, other case #%d)\n",erc); } } void keyGetCheckIntTell(char* key) { unsigned char *stmp; /* Will point into temporary storage */ enum errcode scanres; int ix; stmp = getval((unsigned char *)(key)); printf("For key [%s] the value is [%s].\n", key, stmp); scanres = strchkint(stmp,&ix); if (0 != scanres) { printf("Bad: "); tellproblem(stmp, ix, scanres); } else { int nstart; printf("Good!"); nstart = atoi(stmp); printf(" The value is %d, now let's count: %d %d %d", nstart, nstart+1, nstart+2, nstart+3); } printf("\n"); } int main(void) { printf("Content-type: text/plain;charset=us-ascii\n\n"); printf("Starting to use Peter Burden's form-contents decoder:\n"); keyGetCheckIntTell("num1"); keyGetCheckIntTell("num2"); keyGetCheckIntTell("num3"); keyGetCheckIntTell("num4"); keyGetCheckIntTell("num5"); keyGetCheckIntTell("num6"); keyGetCheckIntTell("num7"); keyGetCheckIntTell("num8"); /* printf("**WARNING** Untested new stuff ...\n"); */ return(0); } ** End of listing of h4int.c ** Here is the directory entry for that source file: -rw------- 1 rem user 6233 Feb 28 2007 h4int.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 9434 Feb 28 2007 h4int-c.cgi ^ Note user execute permission needed for all CGI programs. (because compiled-C is native machine code running directly on machine)