bruce@ogicse.ogc.edu (Bruce Jerrick) (12/15/89)
Description: The behavior of "Fxfile" definitions (in sendmail.cf) with no scanf format changes when readcf.c is compiled with SCANF (enable scanf formats). non-SCANF, no format: enter all words from each line SCANF, no format same as %s, enter first word only This is the case in sendmail 5.59, 5.61, and IDA 1.2.8 . In fact, with the distributed IDA config files, all words in /usr/lib/uucp/L.sys are considered UUCP site names (Any, ACU, etc.!). A better, compatible solution is included below, which eliminates the need for defining SCANF for compilation. Repeat-By: A typical scenario might be: Define UUCP sites in sendmail.cf: FU/usr/lib/uucp/L.sys With SCANF not defined (when compiling readcf.c), any word in L.sys will be considered a valid UUCP site. E.g., try mailing to "ACU!user". Then recompile with SCANF defined (affects readcf.c only), and only the real site names in L.sys will be valid. You may argue that "FU/usr/lib/uucp/L.sys %s" is the proper form, but to enable that, SCANF must be defined, and then the behavior of Fxfile lines without formats will change. And, with SCANF defined, it's messy (at best) to intentionally read in all words of a file line. Fix: The fix eliminates the SCANF compiler macro, and makes the default format be no format, not "%s" (the latter was only effective when compiled with SCANF, hence the behavior change). (Line numbers may vary; if you don't know that already, get some help). *************** *** 38,45 **** ** Cxword Put word into class x. ** Fxfile [fmt] Read file for lines to put into ** class x. Use scanf string 'fmt' ! ** or "%s" if not present. Fmt should ! ** only produce one string-valued result. ** Hname: value Define header with field-name 'name' ** and value as specified; this will be ** macro expanded immediately before --- 38,46 ---- ** Cxword Put word into class x. ** Fxfile [fmt] Read file for lines to put into ** class x. Use scanf string 'fmt' ! ** if present; read all words in a line ! ** if not. 'fmt' must only produce one ! ** string-valued result. ** Hname: value Define header with field-name 'name' ** and value as specified; this will be ** macro expanded immediately before *************** *** 183,191 **** /* read from file */ for (p = &buf[2]; *p != '\0' && !isspace(*p); p++) continue; ! if (*p == '\0') ! p = "%s"; ! else { *p = '\0'; while (isspace(*++p)) --- 184,190 ---- /* read from file */ for (p = &buf[2]; *p != '\0' && !isspace(*p); p++) continue; ! if (*p != '\0') { *p = '\0'; while (isspace(*++p)) *************** *** 299,305 **** ** Parameters: ** class -- class to define. ** filename -- name of file to read. ! ** fmt -- scanf string to use for match. ** ** Returns: ** none --- 298,305 ---- ** Parameters: ** class -- class to define. ** filename -- name of file to read. ! ** fmt -- scanf format string to use for match ! ** (may be null or empty). ** ** Returns: ** none *************** *** 306,313 **** ** ** Side Effects: ** ! ** puts all lines in filename that match a scanf into ! ** the named class. */ fileclass(class, filename, fmt) --- 306,314 ---- ** ** Side Effects: ** ! ** breaks up lines in filename (those matching a scanf format ! ** 'fmt', if present; otherwise all lines) into words ! ** and puts them into the named class. */ fileclass(class, filename, fmt) *************** *** 332,346 **** { register STAB *s; register char *p; - # ifdef SCANF char wordbuf[MAXNAME+1]; ! if (sscanf(buf, fmt, wordbuf) != 1) ! continue; ! p = wordbuf; ! # else SCANF ! p = buf; ! # endif SCANF /* ** Break up the match into words. --- 333,348 ---- { register STAB *s; register char *p; char wordbuf[MAXNAME+1]; ! if (fmt != NULL && *fmt != '\0') ! { ! if (sscanf(buf, fmt, wordbuf) != 1) ! continue; ! p = wordbuf; ! } ! else ! p = buf; /* ** Break up the match into words.