⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 map.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			map->map_mflags &= ~MF_VALID;
		}
	}

	if (restore)
	{
		Errors = saveerrors;
		HoldErrs = savehold;
		QuickAbort = savequick;
	}

	return bitset(MF_OPEN, map->map_mflags);
}
/*
**  CLOSEMAPS -- close all open maps opened by the current pid.
**
**	Parameters:
**		none
**
**	Returns:
**		none.
*/

void
closemaps()
{
	stabapply(map_close, 0);
}
/*
**  MAP_CLOSE -- close a map opened by the current pid.
**
**	Parameters:
**		s -- STAB entry: if map: try to open
**		second parameter is unused (required by stabapply())
**
**	Returns:
**		none.
*/

/* ARGSUSED1 */
static void
map_close(s, unused)
	register STAB *s;
	int unused;
{
	MAP *map;

	if (s->s_type != ST_MAP)
		return;

	map = &s->s_map;

	if (!bitset(MF_VALID, map->map_mflags) ||
	    !bitset(MF_OPEN, map->map_mflags) ||
	    map->map_pid != getpid())
		return;

	if (tTd(38, 5))
		dprintf("closemaps: closing %s (%s)\n",
			map->map_mname == NULL ? "NULL" : map->map_mname,
			map->map_file == NULL ? "NULL" : map->map_file);

	map->map_class->map_close(map);
	map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
}
/*
**  GETCANONNAME -- look up name using service switch
**
**	Parameters:
**		host -- the host name to look up.
**		hbsize -- the size of the host buffer.
**		trymx -- if set, try MX records.
**
**	Returns:
**		TRUE -- if the host was found.
**		FALSE -- otherwise.
*/

bool
getcanonname(host, hbsize, trymx)
	char *host;
	int hbsize;
	bool trymx;
{
	int nmaps;
	int mapno;
	bool found = FALSE;
	bool got_tempfail = FALSE;
	auto int status;
	char *maptype[MAXMAPSTACK];
	short mapreturn[MAXMAPACTIONS];

	nmaps = switch_map_find("hosts", maptype, mapreturn);
	for (mapno = 0; mapno < nmaps; mapno++)
	{
		int i;

		if (tTd(38, 20))
			dprintf("getcanonname(%s), trying %s\n",
				host, maptype[mapno]);
		if (strcmp("files", maptype[mapno]) == 0)
		{
			found = text_getcanonname(host, hbsize, &status);
		}
#ifdef NIS
		else if (strcmp("nis", maptype[mapno]) == 0)
		{
			found = nis_getcanonname(host, hbsize, &status);
		}
#endif /* NIS */
#ifdef NISPLUS
		else if (strcmp("nisplus", maptype[mapno]) == 0)
		{
			found = nisplus_getcanonname(host, hbsize, &status);
		}
#endif /* NISPLUS */
#if NAMED_BIND
		else if (strcmp("dns", maptype[mapno]) == 0)
		{
			found = dns_getcanonname(host, hbsize, trymx, &status);
		}
#endif /* NAMED_BIND */
#if NETINFO
		else if (strcmp("netinfo", maptype[mapno]) == 0)
		{
			found = ni_getcanonname(host, hbsize, &status);
		}
#endif /* NETINFO */
		else
		{
			found = FALSE;
			status = EX_UNAVAILABLE;
		}

		/*
		**  Heuristic: if $m is not set, we are running during system
		**  startup.  In this case, when a name is apparently found
		**  but has no dot, treat is as not found.  This avoids
		**  problems if /etc/hosts has no FQDN but is listed first
		**  in the service switch.
		*/

		if (found &&
		    (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL))
			break;

		/* see if we should continue */
		if (status == EX_TEMPFAIL)
		{
			i = MA_TRYAGAIN;
			got_tempfail = TRUE;
		}
		else if (status == EX_NOTFOUND)
			i = MA_NOTFOUND;
		else
			i = MA_UNAVAIL;
		if (bitset(1 << mapno, mapreturn[i]))
			break;
	}

	if (found)
	{
		char *d;

		if (tTd(38, 20))
			dprintf("getcanonname(%s), found\n", host);

		/*
		**  If returned name is still single token, compensate
		**  by tagging on $m.  This is because some sites set
		**  up their DNS or NIS databases wrong.
		*/

		if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
		{
			d = macvalue('m', CurEnv);
			if (d != NULL &&
			    hbsize > (int) (strlen(host) + strlen(d) + 1))
			{
				if (host[strlen(host) - 1] != '.')
					(void) strlcat(host, ".", hbsize);
				(void) strlcat(host, d, hbsize);
			}
			else
				return FALSE;
		}
		return TRUE;
	}

	if (tTd(38, 20))
		dprintf("getcanonname(%s), failed, status=%d\n", host, status);

#if NAMED_BIND
	if (got_tempfail)
		h_errno = TRY_AGAIN;
	else
		h_errno = HOST_NOT_FOUND;
#endif /* NAMED_BIND */

	return FALSE;
}
/*
**  EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry
**
**	Parameters:
**		name -- the name against which to match.
**		line -- the /etc/hosts line.
**		cbuf -- the location to store the result.
**		cbuflen -- the size of cbuf.
**
**	Returns:
**		TRUE -- if the line matched the desired name.
**		FALSE -- otherwise.
*/

static bool
extract_canonname(name, line, cbuf, cbuflen)
	char *name;
	char *line;
	char cbuf[];
	int cbuflen;
{
	int i;
	char *p;
	bool found = FALSE;

	cbuf[0] = '\0';
	if (line[0] == '#')
		return FALSE;

	for (i = 1; ; i++)
	{
		char nbuf[MAXNAME + 1];

		p = get_column(line, i, '\0', nbuf, sizeof nbuf);
		if (p == NULL)
			break;
		if (*p == '\0')
			continue;
		if (cbuf[0] == '\0' ||
		    (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
		{
			snprintf(cbuf, cbuflen, "%s", p);
		}
		if (strcasecmp(name, p) == 0)
			found = TRUE;
	}
	if (found && strchr(cbuf, '.') == NULL)
	{
		/* try to add a domain on the end of the name */
		char *domain = macvalue('m', CurEnv);

		if (domain != NULL &&
		    strlen(domain) + (i = strlen(cbuf)) + 1 < (size_t) cbuflen)
		{
			p = &cbuf[i];
			*p++ = '.';
			(void) strlcpy(p, domain, cbuflen - i - 1);
		}
	}
	return found;
}
/*
**  NDBM modules
*/

#ifdef NDBM

/*
**  NDBM_MAP_OPEN -- DBM-style map open
*/

bool
ndbm_map_open(map, mode)
	MAP *map;
	int mode;
{
	register DBM *dbm;
	int save_errno;
	int dfd;
	int pfd;
	long sff;
	int ret;
	int smode = S_IREAD;
	char dirfile[MAXNAME + 1];
	char pagfile[MAXNAME + 1];
	struct stat st;
	struct stat std, stp;

	if (tTd(38, 2))
		dprintf("ndbm_map_open(%s, %s, %d)\n",
			map->map_mname, map->map_file, mode);
	map->map_lockfd = -1;
	mode &= O_ACCMODE;

	/* do initial file and directory checks */
	snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file);
	snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file);
	sff = SFF_ROOTOK|SFF_REGONLY;
	if (mode == O_RDWR)
	{
		sff |= SFF_CREAT;
		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
			sff |= SFF_NOSLINK;
		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
			sff |= SFF_NOHLINK;
		smode = S_IWRITE;
	}
	else
	{
		if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
			sff |= SFF_NOWLINK;
	}
	if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
		sff |= SFF_SAFEDIRPATH;
	ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName,
			    sff, smode, &std);
	if (ret == 0)
		ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName,
			       sff, smode, &stp);

# if !_FFR_REMOVE_AUTOREBUILD
	if (ret == ENOENT && AutoRebuild &&
	    bitset(MCF_REBUILDABLE, map->map_class->map_cflags) &&
	    (bitset(MF_IMPL_NDBM, map->map_mflags) ||
	     bitset(MF_ALIAS, map->map_mflags)) &&
	    mode == O_RDONLY)
	{
		bool impl = bitset(MF_IMPL_NDBM, map->map_mflags);

		/* may be able to rebuild */
		map->map_mflags &= ~MF_IMPL_NDBM;
		if (!rebuildaliases(map, TRUE))
			return FALSE;
		if (impl)
			return impl_map_open(map, O_RDONLY);
		else
			return ndbm_map_open(map, O_RDONLY);
	}
# endif /* !_FFR_REMOVE_AUTOREBUILD */

	if (ret != 0)
	{
		char *prob = "unsafe";

		/* cannot open this map */
		if (ret == ENOENT)
			prob = "missing";
		if (tTd(38, 2))
			dprintf("\t%s map file: %d\n", prob, ret);
		if (!bitset(MF_OPTIONAL, map->map_mflags))
			syserr("dbm map \"%s\": %s map file %s",
				map->map_mname, prob, map->map_file);
		return FALSE;
	}
	if (std.st_mode == ST_MODE_NOFILE)
		mode |= O_CREAT|O_EXCL;

# if LOCK_ON_OPEN
	if (mode == O_RDONLY)
		mode |= O_SHLOCK;
	else
		mode |= O_TRUNC|O_EXLOCK;
# else /* LOCK_ON_OPEN */
	if ((mode & O_ACCMODE) == O_RDWR)
	{
#  if NOFTRUNCATE
		/*
		**  Warning: race condition.  Try to lock the file as
		**  quickly as possible after opening it.
		**	This may also have security problems on some systems,
		**	but there isn't anything we can do about it.
		*/

		mode |= O_TRUNC;
#  else /* NOFTRUNCATE */
		/*
		**  This ugly code opens the map without truncating it,
		**  locks the file, then truncates it.  Necessary to
		**  avoid race conditions.
		*/

		int dirfd;
		int pagfd;
		long sff = SFF_CREAT|SFF_OPENASROOT;

		if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail))
			sff |= SFF_NOSLINK;
		if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail))
			sff |= SFF_NOHLINK;

		dirfd = safeopen(dirfile, mode, DBMMODE, sff);
		pagfd = safeopen(pagfile, mode, DBMMODE, sff);

		if (dirfd < 0 || pagfd < 0)
		{
			save_errno = errno;
			if (dirfd >= 0)
				(void) close(dirfd);
			if (pagfd >= 0)
				(void) close(pagfd);
			errno = save_errno;
			syserr("ndbm_map_open: cannot create database %s",
				map->map_file);
			return FALSE;
		}
		if (ftruncate(dirfd, (off_t) 0) < 0 ||
		    ftruncate(pagfd, (off_t) 0) < 0)
		{
			save_errno = errno;
			(void) close(dirfd);
			(void) close(pagfd);
			errno = save_errno;
			syserr("ndbm_map_open: cannot truncate %s.{dir,pag}",
				map->map_file);
			return FALSE;
		}

		/* if new file, get "before" bits for later filechanged check */
		if (std.st_mode == ST_MODE_NOFILE &&
		    (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0))
		{
			save_errno = errno;
			(void) close(dirfd);
			(void) close(pagfd);
			errno = save_errno;
			syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file",
				map->map_file);
			return FALSE;
		}

		/* have to save the lock for the duration (bletch) */
		map->map_lockfd = dirfd;
		(void) close(pagfd);

		/* twiddle bits for dbm_open */
		mode &= ~(O_CREAT|O_EXCL);
#  endif /* NOFTRUNCATE */
	}
# endif /* LOCK_ON_OPEN */

	/* open the database */
	dbm = dbm_open(map->map_file, mode, DBMMODE);
	if (dbm == NULL)
	{
		save_errno = errno;
		if (bitset(MF_ALIAS, map->map_mflags) &&
		    aliaswait(map, ".pag", FALSE))
			return TRUE;
# if !LOCK_ON_OPEN && !NOFTRUNCATE
		if (map->map_lockfd >= 0)
			(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */
		errno = save_errno;
		if (!bitset(MF_OPTIONAL, map->map_mflags))
			syserr("Cannot open DBM database %s", map->map_file);
		return FALSE;
	}
	dfd = dbm_dirfno(dbm);
	pfd = dbm_pagfno(dbm);
	if (dfd == pfd)
	{
		/* heuristic: if files are linked, this is actually gdbm */
		dbm_close(dbm);
# if !LOCK_ON_OPEN && !NOFTRUNCATE
		if (map->map_lockfd >= 0)
			(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */
		errno = 0;
		syserr("dbm map \"%s\": cannot support GDBM",
			map->map_mname);
		return FALSE;
	}

	if (filechanged(dirfile, dfd, &std) ||
	    filechanged(pagfile, pfd, &stp))
	{
		save_errno = errno;
		dbm_close(dbm);
# if !LOCK_ON_OPEN && !NOFTRUNCATE
		if (map->map_lockfd >= 0)
			(void) close(map->map_lockfd);
# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */
		errno = save_errno;
		syserr("ndbm_map_open(%s): file changed after open",
			map->map_file);
		return FALSE;
	}

	map->map_db1 = (ARBPTR_T) dbm;

	/*
	**  Need to set map_mtime before the call to aliaswait()
	**  as aliaswait() will call map_lookup() which requires
	**  map_mtime to be set
	*/

	if (fstat(dfd, &st) >= 0)
		map->map_mtime = st.st_mtime;

	if (mode == O_RDONLY)
	{
# if LOCK_ON_OPEN
		if (dfd >= 0)
			(void) lockfile(dfd, map->map_file, ".dir", LOCK_UN);
		if (pfd >= 0)
			(void) lockfile(pfd, map->map_file, ".pag", LOCK_UN);
# endif /* LOCK_ON_OPEN */
		if (bitset(MF_ALIAS, map->map_mflags) &&
		    !aliaswait(map, ".pag", TRUE))
			return FALSE;
	}
	else
	{
		map->map_mflags |= MF_LOCKED;
		if (geteuid() == 0 && TrustedUid != 0)
		{
#  if HASFCHOWN
			if (fchown(dfd, TrustedUid, -1) < 0 ||
			    fchown(pfd, TrustedUid, -1) < 0)
			{
				int err = errno;

				sm_syslog(LOG_ALERT, NOQID,
					  "ownership change on %s failed: %s",
					  map->map_file, errstring(err));
				message("050 ownership change on %s failed: %s",
					map->map_file, errstring(err));
			}
#  endif /* HASFCHOWN */
		}
	}
	return TRUE;
}


/*
**  NDBM_MAP_LOOKUP -- look up a datum in a DBM-type map
*/

char *
ndbm_map_lookup(map, name, av, statp)
	MAP *map;
	char *name;
	char **av;
	int *statp;
{
	datum key, val;
	int fd;
	char keybuf[MAXNAME + 1];
	struct stat stbuf;

	if (tTd(38, 20))
		dprintf("ndbm_map_lookup(%s, %s)\n",
			map->map_mname, name);

	key.dptr = name;
	key.dsize = strlen(name);
	if (!bitset(MF_NOFOLDCASE, map->map_mflags))
	{
		if (key.dsize > sizeof keybuf - 1)
			key.dsize = sizeof keybuf - 1;
		memmove(keybuf, key.dptr, key.dsize);
		keybuf[key.dsize] = '\0';
		makelower(keybuf);
		key.dptr = keybuf;
	}
lockdbm:
	fd = dbm_dirfno((DBM *) map->map_db1);
	if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
		(void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
	if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
	{
		/* Reopen the database to sync the cache */
		int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR

⌨️ 快捷键说明

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