db_load.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,648 行 · 第 1/3 页

C
1,648
字号
#ifndef lintstatic	char	*sccsid = "@(#)db_load.c	4.2	(ULTRIX)	11/15/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1984-1990 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Copyright (c) 1986 Regents of the University of California *	All Rights Reserved * static char sccsid[] = "@(#)db_load.c	4.26 (Berkeley) 2/28/88"; *//* * Modification History: * * 18-Jan-88	logcher *	Added BIND 4.7.2 with ifdef-ed MIT Hesiod support. * * 26-Jan-88	logcher *	Added BIND 4.7.3. * * 08-Jun-88	logcher *	Added the correct MIT Hesiod support. * * 11-Nov-88	logcher *	Updated with V3.0 changes. * * 17-May-89	logcher *	Added BIND 4.8 with MIT Hesiod support. * * 10-Jan-90	sue *	Incorporated Hesiod changes from MIT to implement multiple *	"character strings" in a TXT record according to RFC1035. *//* * Load data base from ascii backupfile.  Format similar to RFC 883. */#include <sys/param.h>#include <sys/time.h>#include <sys/stat.h>#include <netinet/in.h>#include <stdio.h>#include <syslog.h>#include <ctype.h>#include <netdb.h>#include <arpa/nameser.h>#include "ns.h"#include "db.h"extern char *index();extern int max_cache_ttl;/* * Map class and type names to number */struct map {	char	token[8];	int	val;};struct map m_class[] = {	"in",		C_IN,#ifdef notdef	"any",		C_ANY,		/* any is a QCLASS, not CLASS */#endif	"chaos",	C_CHAOS,	"hs",		C_HS,};#define NCLASS (sizeof(m_class)/sizeof(struct map))struct map m_type[] = {	"a",		T_A,	"ns",		T_NS,	"cname",	T_CNAME,	"soa",		T_SOA,	"mb",		T_MB,	"mg",		T_MG,	"mr",		T_MR,	"null",		T_NULL,	"wks",		T_WKS,	"ptr",		T_PTR,	"hinfo",	T_HINFO,	"minfo",	T_MINFO,	"mx",		T_MX,	"uinfo",	T_UINFO,	"uid",		T_UID,	"gid",		T_GID,	"txt",		T_TXT,#ifdef notdef	"any",		T_ANY,		/* any is a QTYPE, not TYPE */#endif#ifdef ALLOW_T_UNSPEC        "unspec",       T_UNSPEC,#endif ALLOW_T_UNSPEC};#define NTYPE (sizeof(m_type)/sizeof(struct map))/* * Parser token values */#define CURRENT	1#define DOT	2#define AT	3#define DNAME	4#define INCLUDE	5#define ORIGIN	6#define ERROR	7int	lineno;		/* current line number */struct valuelist {	struct valuelist *next, *prev;	char	*name;	char	*proto;	short	port;} *servicelist, *protolist;file_ref_st *load_prep(zp, filename, origin, zonenum)	struct zoneinfo *zp;	char *filename;		char *origin;        int zonenum;{	file_ref_st *load_info;	if((load_info = (file_ref_st *)malloc(sizeof(file_ref_st))) == NULL) {		syslog(LOG_ERR, "load_prep: Bad Malloc.\n");#ifdef DEBUG		if (debug) 			fprintf(ddt,"load_prep: Bad Malloc.\n");#endif		return(NULL);	}	if((load_info->files = (files_st *)malloc(sizeof(files_st))) == NULL) {		syslog(LOG_ERR, "load_prep: Bad Malloc.\n");#ifdef DEBUG		if (debug) 			fprintf(ddt,"load_prep: Bad Malloc.\n");#endif		free(load_info);		return(NULL);	}	if((load_info->zp = (struct zoneinfo *)	    malloc(sizeof(struct zoneinfo))) == NULL) {		syslog(LOG_ERR, "load_prep: Bad Malloc.\n");#ifdef DEBUG		if (debug) 			fprintf(ddt,"load_prep: Bad Malloc.\n");#endif		free(load_info->files);		free(load_info);		return(NULL);	}	zp->z_load_info = load_info;	set_zp(zp, load_info->zp);	(void) strcpy(load_info->files->f_name, filename);	load_info->files->next = NULL;	load_info->files_tail = load_info->files;	load_info->fp = NULL;	(void) strcpy(load_info->origin, origin);	load_info->next = NULL;	load_info->zonenum = zonenum;	return(load_info);}#ifdef ULTRIXFUNCdb_load(load_info, num_iter)	file_ref_st *load_info;	/* pointer to the structure which				   describes what data to load. */	int num_iter;		/* the number of iterations through the while				   loop below that this function should go				   through.  If an include entry is found,				   num_iter is overrided.  If num_iter == -1				   then no limit exists. */{	register struct zoneinfo *zp;	register char domain[MAXDNAME];	register char origin[MAXDNAME];	register FILE *fp;	register u_char *cp;	register struct map *mp;	char tmporigin[MAXDNAME];	u_char buf[MAXDATA], *tmpdata, *tmpbuf;	u_char data[MAXDATA];	char *op;	int c;	int class, type;	int ttl;	struct databuf *dp;	int i, errs = -2;	int result;	FILE *fp_in;/* If T_UNSPEC is used, this can't be a register variable. */#ifndef ALLOW_T_UNSPEC	register u_long n;#else	u_long n;#endif	if(load_info->next != NULL) {				if((result = db_load(load_info->next, num_iter)) < -2) {			errs = result;			goto err;		} else {			if(result == -2)				return(-2);			else {				load_info->format_errs +=					load_info->next->format_errs;				free(load_info->next);				load_info->next = NULL;				num_iter = result;			}		}	} else {		if(num_iter < -1)			errs--;	}	if(load_info->fp == NULL) {		/* This load_info struct has not been initialized.  Start			reading the file from the start. */#ifdef DEBUG		if (debug)			fprintf(ddt,"db_load(%s, %s, %d)\n",				load_info->zp->z_source, load_info->origin,				load_info->zonenum);#endif		/*  */		if ((load_info->fp = fopen(load_info->files->f_name, "r")) == NULL) {			if (load_info->zp->z_type != Z_SECONDARY)				syslog(LOG_ERR,"db_load: error opening file %s\n", 					load_info->files->f_name);#ifdef DEBUG			if (debug)			    fprintf(ddt,"db_load: error opening file %s\n",				load_info->files->f_name);#endif			errs--;			goto err;		}		load_info->lineno = 1;		if (load_info->zp->z_type == Z_CACHE) {		    load_info->dbflags = DB_NODATA | DB_NOHINTS;		    load_info->dataflags = DB_F_HINT;		} else {		    load_info->dbflags = DB_NODATA;		    load_info->dataflags = 0;		}		gettime(&tt);		if (fstat(fileno(load_info->fp), &load_info->files->f_stats) < 0) {			syslog(LOG_ERR,"db_load: error in fstat, file %s\n",				load_info->files->f_name);#ifdef DEBUG			if (debug)			    fprintf(ddt,"db_load: error in fstat file %s\n",				load_info->files->f_name);#endif			errs--;			goto err;		}		if(load_info->files->f_stats.st_mtime >	load_info->zp->z_ftime)			load_info->zp->z_ftime = load_info->files->f_stats.st_mtime;		/* A primary assumes that the data in the load file is		   is not in the process of expiring. */		if(load_info->zp->z_type == Z_PRIMARY)			load_info->zp->z_lastupdate = tt.tv_sec;		else			load_info->zp->z_lastupdate = load_info->files->f_stats.st_mtime;		load_info->domain[0] = '\0';		load_info->class = C_IN;		load_info->format_errs = 0;	}	/* copy the following vars into stackspace in order to prevent	   any de-referencing */	fp = load_info->fp;	zp = load_info->zp;	(void) strcpy(origin, load_info->origin);	(void) strcpy(domain, load_info->domain);	/* Set lineno to the line in cur_file that we are "reading". */	lineno = load_info->lineno;	class = load_info->class;	/* We have started to read the file.  continue. */	while ((num_iter == -1 || num_iter - 1 >= 0) &&			(c = gettoken(fp)) != EOF &&			(num_iter == -1 || --num_iter >= 0)) {					switch (c) {		case INCLUDE:			/* An include entry implies that another file should			   be read at this point.  Copy all of the new 			   file to the temp file, and set environment vars */							if (!getword(buf, sizeof(buf), fp)) /* file name */				break;			if (!getword(tmporigin, sizeof(tmporigin), fp))				strcpy(tmporigin, origin);			else {				makename(tmporigin, origin);				endline(fp);			}			if((load_info->next =			    load_prep(zp, buf, tmporigin,				      load_info->zonenum)) == NULL){				syslog(LOG_ERR, "Bad load_prep call");				errs--;				goto err;			}							free(load_info->next->zp);			load_info->next->zp = zp;			zp->z_load_info = load_info;			load_info->lineno = lineno;			/* if num_iter == -1 then process till the end			   otherwise, consider the copying of an entire			   file enough steps to use all of num_iter. */			if (num_iter != -1)				num_iter = 1;			if((result = db_load(load_info->next,num_iter)) < -2) {				free(load_info->next);				load_info->next = NULL;				errs = result;				goto err;			}			lineno = load_info->lineno;			load_info->files_tail->next = load_info->next->files;			load_info->files_tail = load_info->next->files_tail;			if(result == -2) {				num_iter = 0;			} else {				load_info->format_errs +=					load_info->next->format_errs;				free(load_info->next);				load_info->next = NULL;				num_iter = result;			}			continue;		case ORIGIN:			(void) strcpy(buf, origin);			if (!getword(origin, sizeof(origin), fp))				break;#ifdef DEBUG			if (debug > 3)				fprintf(ddt,"db_load: origin %s, buf %s\n",				    origin, buf);#endif			makename(origin, buf);#ifdef DEBUG			if (debug > 3)				fprintf(ddt,"db_load: origin now %s\n", origin);#endif			continue;		case DNAME:			if (!getword(domain, sizeof(domain), fp))				break;			n = strlen(domain) - 1;			if (domain[n] == '.')				domain[n] = '\0';			else if (*origin) {				(void) strcat(domain, ".");				(void) strcat(domain, origin);			}			goto gotdomain;		case AT:			(void) strcpy(domain, origin);			goto gotdomain;		case DOT:			domain[0] = '\0';			/* fall thru ... */		case CURRENT:		gotdomain:			if (!getword(buf, sizeof(buf), fp)) {				if (c == CURRENT)					continue;				break;			}			cp = buf;			ttl = 0;			if (isdigit(*cp)) {				n = 0;				do					n = n * 10 + (*cp++ - '0');				while (isdigit(*cp));				if (zp->z_type == Z_CACHE) {				    /* this allows the cache entry to age */				    /* while sitting on disk (powered off) */				    if (n > max_cache_ttl)					n = max_cache_ttl;				    n += load_info->files->f_stats.st_mtime;				}				ttl = n;				if (!getword(buf, sizeof(buf), fp))					break;			}			for (mp = m_class; mp < m_class+NCLASS; mp++)				if (!strcasecmp(buf, mp->token)) {					class = mp->val;					(void) getword(buf, sizeof(buf), fp);					break;				}			for (mp = m_type; mp < m_type+NTYPE; mp++)				if (!strcasecmp(buf, mp->token)) {					type = mp->val;					goto fndtype;				}#ifdef DEBUG			if (debug)				fprintf(ddt,"Line %d: Unknown type: %s.\n",					lineno, buf);#endif			load_info->format_errs++; 			syslog(LOG_ERR, "Line %d: Unknown type: %s.\n",				lineno, buf);			break;		fndtype:#ifdef ALLOW_T_UNSPEC			/* Don't do anything here for T_UNSPEC...			 * read input separately later			 */                        if (type != T_UNSPEC) {#endif ALLOW_T_UNSPEC			    if (!getword(buf, sizeof(buf), fp))				break;#ifdef DEBUG			    if (debug >= 3)			        fprintf(ddt,				    "d='%s', c=%d, t=%d, ttl=%d, data='%s'\n",				    domain, class, type, ttl, buf);#endif#ifdef ALLOW_T_UNSPEC                        }#endif ALLOW_T_UNSPEC			/*			 * Convert the ascii data 'buf' to the proper format			 * based on the type and pack into 'data'.			 */			switch (type) {			case T_A:				n = ntohl((u_long)inet_addr((char *)buf));				cp = data;				PUTLONG(n, cp);				n = sizeof(u_long);				break;			case T_HINFO:				n = strlen(buf);				if (n > 255) {				    syslog(LOG_WARNING,					"%s: line %d: CPU type too long",					load_info->files->f_name, lineno);				    n = 255;				}				data[0] = n;				bcopy(buf, (char *)data + 1, (int)n);				n++;				if (!getword(buf, sizeof(buf), fp))					break;				i = strlen(buf);				if (i > 255) {				    syslog(LOG_WARNING,					"%s: line %d: OS type too long",					load_info->files->f_name, lineno);				    i = 255;				}				data[n] = i;				bcopy(buf, data + n + 1, i);				n += i + 1;				endline(fp);				break;			case T_SOA:			case T_MINFO:				(void) strcpy(data, buf);				makename(data, origin);				cp = data + strlen(data) + 1;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?