/* ************************************************************** * Functions to read the input stream in an attempt to match incoming * data to the current pattern from the main loop of _doscan(). ************************************************************** */ static int number(int stow, int type, int len, int size, FILE *iop, va_list *listp) { char numbuf[64], inchar, lookahead; char *np = numbuf; int c, base; int digitseen = 0, floater = 0, negflg = 0; long lcval = 0; switch(type) { case 'e': case 'f': case 'g': floater++; case 'd': case 'u': case 'i': base = 10; break; case 'o': base = 8; break; case 'x': base = 16; break; default: return(0); /* unrecognized conversion character */ } if (!flag_eof) { while (isws(c = locgetc())) ; } else c = locgetc(); if (c == EOF) { chcount--; return(-1); /* EOF before match */ } if (floater != 0) { /* Handle floating point with * file_to_decimal. */ decimal_mode dm; decimal_record dr; fp_exception_field_type efs; enum decimal_string_form form; char *echar; int nread, ic; char buffer[1024]; char *nb = buffer; locungetc(c); if (len > 1024) len = 1024; file_to_decimal(&nb, len, 0, &dr, &form, &echar, iop, &nread); if (stow && (form != invalid_form)) { dm.rd = fp_direction; if (size == 'l') { /* double */ decimal_to_double((double *) va_arg(*listp, double *), &dm, &dr, &efs); } else if (size == 'L') { /* quad */
int _doscan(FILE *iop, unsigned char *fmt, va_list va_alist) { char tab[NCHARS]; int ch; int nmatch = 0, len, inchar, stow, size; chcount=0; flag_eof=0; /******************************************************* * Main loop: reads format to determine a pattern, * and then goes to read input stream * in attempt to match the pattern. *******************************************************/ for ( ; ; ) { if ( (ch = *fmt++) == '\0') return(nmatch); /* end of format */ if (isws(ch)) { if (!flag_eof) { while (isws(inchar = locgetc())) ; if (inchar == EOF) { chcount--; flag_eof = 1; } else if (locungetc(inchar) == EOF) flag_eof = 1; } continue; } if (ch != '%' || (ch = *fmt++) == '%') { if ( (inchar = locgetc()) == ch ) continue; if (inchar != EOF) { if (locungetc(inchar) != EOF) return(nmatch); /* failed to match input */ } else { chcount--; } break; } if (ch == '*') { stow = 0; ch = *fmt++; } else stow = 1; for (len = 0; isdigit(ch); ch = *fmt++) len = len * 10 + ch - '0'; if (len == 0) len = MAXINT; if ( (size = ch) == 'l' || (size == 'h') || (size == 'L') ) ch = *fmt++; if (ch == '\0' || ch == '[' && (fmt = setup(fmt, tab)) == NULL) return(EOF); /* unexpected end of format */ if (isupper(ch)) /* no longer documented */ { /* * The rationale behind excluding the size * of 'L' is that the 'L' size specifier was * introduced in ANSI/ISO-C. If the user * specifies a format of %LG, it can mean * nothing other than "long double", be the * code ANSI or not. Mapping it to "double" * makes no sense. */ if (size != 'L') size = 'l'; #ifdef S5EMUL ch = _tolower(ch); #else ch = tolower(ch); #endif } switch(ch) { case 'c': case 's': case '[': if ((size = string(stow,ch,len,tab,iop,&va_alist)) < 0) goto out; /* EOF seen, nothing converted */ break; case 'n': if (stow == 0) continue; if (size == 'h') *va_arg(va_alist, short *) = (short) chcount; else if (size == 'l') *va_arg(va_alist, long *) = (long) chcount; else *va_arg(va_alist, int *) = (int) chcount; continue; default: if ((size = number(stow, ch, len, size, iop, &va_alist)) < 0) goto out; /* EOF seen, nothing converted */ break; } if (size) nmatch += stow; else return((flag_eof && !nmatch) ? EOF : nmatch); continue; } out: return (nmatch != 0 ? nmatch : EOF); /* end of input */ }
/* nearly untouched function from cgic0.5 - works fine */ int parseQueryString(const char *str, int length) /* if str is NULL, read from stdin */ { unsigned int i = 0; int c, valuei, namei; /* char *name=(char*)strdup(""), *value=(char*)strdup(""); */ char *name=malloc(length); /* Fixed by BCH 1/15/01 */ char *value=malloc(length); /* Fixed by BCD 1/15/01 */ strcpy(name, ""); strcpy(value, ""); while (i < length) { namei=0; while (i < length) { /* if str!=NULL => read string, we got from getenv - else, read stdin */ c=locgetc(str, i); if (c == EOF) return false; i++; if (c == '=' || c == '&') break; /* name=realloc(name, namei+1); */ /* Fixed by BCH 1/15/01 */ name[namei++]=c; } name[namei] = 0; /* After an entry name, always expecting to find '='. */ if (c != '=') { cgi_errno = CGIERR_IURLENC; return false; } valuei=0; while (i < length) { c = locgetc(str, i); if (c == EOF) return false; i++; if (c == '&' || c == '=') break; /* value=realloc(value, valuei+1); */ /* Fixed by BCH 1/15/01 */ value[valuei++]=c; } /* If this isn't the last entry, expecting to find '&' after it. If it's the last, but there is '&' - error. */ if (i < length) { if (c != '&') { cgi_errno = CGIERR_IURLENC; return 0; } } else if (c == '&') { cgi_errno = CGIERR_IURLENC; return 0; } /* Here check is not needed, because valbuf_index is always less than CGI_MAXVAL and valbuf is CGI_MAXVAL+1 bytes long. */ value[valuei] = 0; if (!miscStringDecode(name) || !miscStringDecode(value)) { cgi_errno = CGIERR_IURLENC; return 0; } if(!listAddData(CgiKindValue, name, value, NULL, NULL)) return(false); } free(name); free(value); return true; }