📄 nslint.c
字号:
sawcomment = 0; \ if (*cp == '#') { \ sawcomment = 1; \ ++cp; \ while (*cp != '\n' && *cp != '\0') \ ++cp; \ } \ else if (strncmp(cp, "//", 2) == 0) { \ sawcomment = 1; \ cp += 2; \ while (*cp != '\n' && *cp != '\0') \ ++cp; \ } \ else if (strncmp(cp, "/*", 2) == 0) { \ sawcomment = 1; \ for (cp += 2; *cp != '\0'; ++cp) { \ if (*cp == '\n') \ ++n; \ else if (strncmp(cp, "*/", 2) == 0) { \ cp += 2; \ break; \ } \ } \ } \ } while (sawcomment); \ }#define GETNAME(name, len) \ { \ (name) = cp; \ (len) = 0; \ while (!isspace(*cp) && *cp != ';' && *cp != '\0') { \ ++(len); \ ++cp; \ } \ }#define GETQUOTEDNAME(name, len) \ { \ if (*cp != '"') { \ ++errors; \ fprintf(stderr, "%s: %s:%d missing left quote\n", \ prog, file, n); \ } else \ ++cp; \ (name) = cp; \ (len) = 0; \ while (*cp != '"' && *cp != '\n' && *cp != '\0') { \ ++(len); \ ++cp; \ } \ if (*cp != '"') { \ ++errors; \ fprintf(stderr, "%s: %s:%d missing right quote\n", \ prog, file, n); \ } else \ ++cp; \ }/* Eat everything to the next semicolon, perhaps eating matching qbraces */#define EATSEMICOLON \ { \ register int depth = 0; \ while (*cp != '\0') { \ EATCOMMENTS \ if (*cp == ';') { \ ++cp; \ if (depth == 0) \ break; \ continue; \ } \ if (*cp == '{') { \ ++depth; \ ++cp; \ continue; \ } \ if (*cp == '}') { \ --depth; \ ++cp; \ continue; \ } \ ++cp; \ } \ } n = 1; zone[0] = '\0'; cp = buf; while (*cp != '\0') { EATCOMMENTS if (*cp == '\0') break; GETNAME(name, namelen) if (namelen == 0) { ++errors; fprintf(stderr, "%s: %s:%d garbage char '%c' (1)\n", prog, file, n, *cp); ++cp; continue; } EATCOMMENTS if (strncasecmp(name, "options", namelen) == 0) { EATCOMMENTS if (*cp != '{') { ++errors; fprintf(stderr, "%s: %s:%d missing left qbrace in options\n", prog, file, n); } else ++cp; EATCOMMENTS while (*cp != '}' && *cp != '\0') { EATCOMMENTS GETNAME(name, namelen) if (namelen == 0) { ++errors; fprintf(stderr, "%s: %s:%d garbage char '%c' (2)\n", prog, file, n, *cp); ++cp; break; } /* If not the "directory" option, just eat it */ if (strncasecmp(name, "directory", namelen) == 0) { EATCOMMENTS GETQUOTEDNAME(cp2, i) cp2[i] = '\0'; if (chdir(cp2) < 0) { ++errors; fprintf(stderr, "%s: %s:.%d can't chdir %s: %s\n", prog, file, n, cp2, strerror(errno)); exit(1); } cwd = savestr(cp2); } EATSEMICOLON EATCOMMENTS } ++cp; EATCOMMENTS if (*cp != ';') { ++errors; fprintf(stderr, "%s: %s:%d missing options semi\n", prog, file, n); } else ++cp; continue; } if (strncasecmp(name, "zone", namelen) == 0) { EATCOMMENTS GETQUOTEDNAME(zonename, zonenamelen) typename = NULL; filename = NULL; typenamelen = 0; filenamelen = 0; EATCOMMENTS if (strncasecmp(cp, "in", 2) == 0) { cp += 2; EATWHITESPACE } else if (strncasecmp(cp, "chaos", 5) == 0) { cp += 5; EATWHITESPACE } if (*cp != '{') { /* } */ ++errors; fprintf(stderr, "%s: %s:%d missing left qbrace in zone\n", prog, file, n); continue; } depth = 0; EATCOMMENTS while (*cp != '\0') { if (*cp == '{') { ++cp; ++depth; } else if (*cp == '}') { if (--depth <= 1) break; ++cp; } EATCOMMENTS GETNAME(name, namelen) if (namelen == 0) { ++errors; fprintf(stderr, "%s: %s:%d garbage char '%c' (3)\n", prog, file, n, *cp); ++cp; break; } if (strncasecmp(name, "type", namelen) == 0) { EATCOMMENTS GETNAME(typename, typenamelen) if (namelen == 0) { ++errors; fprintf(stderr, "%s: %s:%d garbage char '%c' (4)\n", prog, file, n, *cp); ++cp; break; } } else if (strncasecmp(name, "file", namelen) == 0) { EATCOMMENTS GETQUOTEDNAME(filename, filenamelen) } /* Just ignore keywords we don't understand */ EATSEMICOLON EATCOMMENTS } /* { */ if (*cp != '}') { ++errors; fprintf(stderr, "%s: %s:%d missing zone right qbrace\n", prog, file, n); } else ++cp; if (*cp != ';') { ++errors; fprintf(stderr, "%s: %s:%d missing zone semi\n", prog, file, n); } else ++cp; EATCOMMENTS /* If we got something interesting, process it */ if (typenamelen == 0) { ++errors; fprintf(stderr, "%s: missing zone type!\n", prog); continue; } if (strncasecmp(typename, "master", typenamelen) == 0) { if (filenamelen == 0) { ++errors; fprintf(stderr, "%s: missing zone filename!\n", prog); continue; } strncpy(zone, zonename, zonenamelen); zone[zonenamelen] = '\0'; for (cp2 = zone; *cp2 != '\0'; ++cp2) if (isupper(*cp2)) *cp2 = tolower(*cp2); /* Insure trailing dot */ if (cp2 > zone && cp2[-1] != '.') { *cp2++ = '.'; *cp2 = '\0'; } filename[filenamelen] = '\0'; nsoaval = -1; memset(soaval, 0, sizeof(soaval)); process(filename, zone, zone); } continue; } if (strncasecmp(name, "nslint", namelen) == 0) { EATCOMMENTS if (*cp != '{') { ++errors; fprintf(stderr, "%s: %s:%d missing left qbrace in nslint\n", prog, file, n); } else ++cp; ++cp; EATCOMMENTS while (*cp != '}' && *cp != '\0') { EATCOMMENTS GETNAME(name, namelen) if (strncasecmp(name, "network", namelen) == 0) { EATCOMMENTS GETQUOTEDNAME(cp2, i) cp2[i] = '\0'; if (!parsenetwork(cp2, &errstr)) { ++errors; fprintf(stderr, "%s: %s:%d: bad network: %s\n", prog, file, n, errstr); } } else { ++errors; fprintf(stderr, "%s: unknown nslint \"%.*s\"\n", prog, namelen, name); } EATSEMICOLON EATCOMMENTS } ++cp; EATCOMMENTS if (*cp != ';') { ++errors; fprintf(stderr, "missing options semi\n"); } else ++cp; continue; } if (strncasecmp(name, "include", namelen) == 0) { EATCOMMENTS GETQUOTEDNAME(filename, filenamelen) strncpy(includefile, filename, filenamelen); includefile[filenamelen] = '\0'; errors += doconf(includefile, 1); EATSEMICOLON continue; } /* Skip over statements we don't understand */ EATSEMICOLON } free(buf); close(fd); return (errors != 0);}/* Return true when done */intparsesoa(register const char *cp, register char **errstrp){ register char ch, *garbage; static char errstr[132]; /* Eat leading whitespace */ while (isspace(*cp)) ++cp; /* Find opening paren */ if (nsoaval < 0) { cp = strchr(cp, '('); if (cp == NULL) return (0); ++cp; while (isspace(*cp)) ++cp; nsoaval = 0; } /* Grab any numbers we find */ garbage = "leading garbage"; while (isdigit(*cp) && nsoaval < NSOAVAL) { soaval[nsoaval] = atoi(cp); do { ++cp; } while (isdigit(*cp)); if (nsoaval == SOA_SERIAL && *cp == '.' && isdigit(cp[1])) { do { ++cp; } while (isdigit(*cp)); } else { ch = *cp; if (isupper(ch)) ch = tolower(ch); switch (ch) { case 'w': soaval[nsoaval] *= 7; /* fall through */ case 'd': soaval[nsoaval] *= 24; /* fall through */ case 'h': soaval[nsoaval] *= 60; /* fall through */ case 'm': soaval[nsoaval] *= 60; /* fall through */ case 's': ++cp; break; default: ; /* none */ } } while (isspace(*cp)) ++cp; garbage = "trailing garbage"; ++nsoaval; } /* If we're done, do some sanity checks */ if (nsoaval >= NSOAVAL && *cp == ')') { ++cp; if (*cp != '\0') *errstrp = garbage; else if (soaval[SOA_EXPIRE] < soaval[SOA_REFRESH] + 10 * soaval[SOA_RETRY]) { (void)sprintf(errstr, "expire less than refresh + 10 * retry (%u < %u + 10 * %u)", soaval[SOA_EXPIRE], soaval[SOA_REFRESH], soaval[SOA_RETRY]); *errstrp = errstr; } else if (soaval[SOA_REFRESH] < 2 * soaval[SOA_RETRY]) { (void)sprintf(errstr, "refresh less than 2 * retry (%u < 2 * %u)", soaval[SOA_REFRESH], soaval[SOA_RETRY]); *errstrp = errstr; } return (1); } if (*cp != '\0') { *errstrp = garbage; return (1); } return (0);}voidprocess(register const char *file, register const char *domain, register const char *zone){ register FILE *f; register char ch, *cp, *cp2, *cp3, *rtype; register const char *ccp; register int n, sawsoa, flags, i; register u_int ttl; register u_int32_t addr; u_int32_t net, mask; int smtp; char buf[1024], name[128], lastname[128], odomain[128]; char *errstr; char *dotfmt = "%s: %s/%s:%d \"%s\" target missing trailing dot: %s\n"; f = fopen(file, "r"); if (f == NULL) { fprintf(stderr, "%s: %s/%s: %s\n", prog, cwd, file, strerror(errno)); ++errors; return; } if (debug > 1) printf("%s: process: opened %s/%s\n", prog, cwd, file); /* Are we doing an in-addr.arpa domain? */ n = 0; net = 0; mask = 0; ccp = domain + strlen(domain) - sizeof(inaddr) + 1; if (ccp >= domain && strcasecmp(ccp, inaddr) == 0 && !parseinaddr(domain, &net, &mask)) { ++errors; fprintf(stderr, "%s: %s/%s:%d bad in-addr.arpa domain\n", prog, cwd, file, n); return; } lastname[0] = '\0'; sawsoa = 0; while (fgets(buf, sizeof(buf), f) != NULL) { ++n; cp = buf; while (*cp != '\0') { /* Handle quoted strings (but don't report errors) */ if (*cp == '"') { ++cp; while (*cp != '"' && *cp != '\n' && *cp != '\0') ++cp; continue; } if (*cp == '\n' || *cp == ';') break; ++cp; } *cp-- = '\0'; /* Nuke trailing white space */ while (cp >= buf && isspace(*cp)) *cp-- = '\0'; cp = buf; if (*cp == '\0') continue; /* Handle multi-line soa records */ if (sawsoa) { errstr = NULL; if (parsesoa(cp, &errstr)) sawsoa = 0; if (errstr != NULL) { ++errors; fprintf(stderr, "%s: %s/%s:%d bad \"soa\" record (%s)\n", prog, cwd, file, n, errstr); } continue; } if (debug > 3) printf(">%s<\n", cp); /* Look for name */ if (isspace(*cp)) { /* Same name as last record */ if (lastname[0] == '\0') { ++errors; fprintf(stderr, "%s: %s/%s:%d no default name\n", prog, cwd, file, n); continue; } (void)strcpy(name, lastname); } else { /* Extract name, converting to lowercase */ for (cp2 = name; !isspace(*cp) && *cp != '\0'; ++cp) if (isupper(*cp)) *cp2++ = tolower(*cp); else *cp2++ = *cp; *cp2 = '\0'; /* Check for domain shorthand */ if (name[0] == '@' && name[1] == '\0') (void)strcpy(name, domain); } /* Find next token */ while (isspace(*cp)) ++cp; /* Handle includes (gag) */ if (name[0] == '$' && strcasecmp(name, "$include") == 0) { /* Extract filename */ cp2 = name; while (!isspace(*cp) && *cp != '\0') *cp2++ = *cp++; *cp2 = '\0'; /* Look for optional domain */ while (isspace(*cp)) ++cp; if (*cp == '\0') process(name, domain, zone); else { cp2 = cp; /* Convert optional domain to lowercase */ for (; !isspace(*cp) && *cp != '\0'; ++cp) if (isupper(*cp)) *cp = tolower(*cp); *cp = '\0'; process(name, cp2, cp2); } continue; } /* Handle $origin */ if (name[0] == '$' && strcasecmp(name, "$origin") == 0) { /* Extract domain, converting to lowercase */ for (cp2 = odomain; !isspace(*cp) && *cp != '\0'; ++cp) if (isupper(*cp)) *cp2++ = tolower(*cp); else *cp2++ = *cp; *cp2 = '\0'; domain = odomain; lastname[0] = '\0'; /* Are we doing an in-addr.arpa domain? */ net = 0; mask = 0; ccp = domain + strlen(domain) - (sizeof(inaddr) - 1); if (ccp >= domain && strcasecmp(ccp, inaddr) == 0 && !parseinaddr(domain, &net, &mask)) { ++errors; fprintf(stderr, "%s: %s/%s:%d bad in-addr.arpa domain\n", prog, cwd, file, n); return; } continue; } /* Handle ttl */ if (name[0] == '$' && strcasecmp(name, "$ttl") == 0) { cp2 = cp; while (isdigit(*cp))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -