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

📄 mci.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:

	errno = save_errno;
	return;
}
/*
**  MCI_TRAVERSE_PERSISTENT -- walk persistent status tree
**
**	Recursively find all the mci host files in `pathname'.  Default to
**		main host status directory if no path is provided.
**	Call (*action)(pathname, host) for each file found.
**
**	Note: all information is collected in a list before it is processed.
**	This may not be the best way to do it, but it seems safest, since
**	the file system would be touched while we are attempting to traverse
**	the directory tree otherwise (during purges).
**
**	Parameters:
**		action -- function to call on each node.  If returns < 0,
**			return immediately.
**		pathname -- root of tree.  If null, use main host status
**			directory.
**
**	Returns:
**		< 0 -- if any action routine returns a negative value, that
**			value is returned.
**		0 -- if we successfully went to completion.
**		> 0 -- return status from action()
*/

int
mci_traverse_persistent(action, pathname)
	int (*action)();
	char *pathname;
{
	struct stat statbuf;
	DIR *d;
	int ret;

	if (pathname == NULL)
		pathname = HostStatDir;
	if (pathname == NULL)
		return -1;

	if (tTd(56, 1))
		dprintf("mci_traverse: pathname is %s\n", pathname);

	ret = stat(pathname, &statbuf);
	if (ret < 0)
	{
		if (tTd(56, 2))
			dprintf("mci_traverse: Failed to stat %s: %s\n",
				pathname, errstring(errno));
		return ret;
	}
	if (S_ISDIR(statbuf.st_mode))
	{
		struct dirent *e;
		char *newptr;
		char newpath[MAXPATHLEN + 1];
		bool leftone, removedone;

		if ((d = opendir(pathname)) == NULL)
		{
			if (tTd(56, 2))
				dprintf("mci_traverse: opendir %s: %s\n",
					pathname, errstring(errno));
			return -1;
		}

		if (strlen(pathname) >= sizeof newpath - MAXNAMLEN - 3)
		{
			if (tTd(56, 2))
				dprintf("mci_traverse: path \"%s\" too long",
					pathname);
			return -1;
		}
		(void) strlcpy(newpath, pathname, sizeof newpath);
		newptr = newpath + strlen(newpath);
		*newptr++ = '/';

		/*
		**  repeat until no file has been removed
		**  this may become ugly when several files "expire"
		**  during these loops, but it's better than doing
		**  a rewinddir() inside the inner loop
		*/
		do
		{
			leftone = removedone = FALSE;
			while ((e = readdir(d)) != NULL)
			{
				if (e->d_name[0] == '.')
					continue;

				(void) strlcpy(newptr, e->d_name,
					       sizeof newpath -
					       (newptr - newpath));

				ret = mci_traverse_persistent(action, newpath);
				if (ret < 0)
					break;
				if (ret == 1)
					leftone = TRUE;
				if (!removedone && ret == 0 &&
				    action == mci_purge_persistent)
					removedone = TRUE;
			}
			if (ret < 0)
				break;
			/*
			**  The following appears to be
			**  necessary during purges, since
			**  we modify the directory structure
			*/
			if (removedone)
				rewinddir(d);
			if (tTd(56, 40))
				dprintf("mci_traverse: path %s: ret %d removed %d left %d\n",
					pathname, ret, removedone, leftone);
		} while (removedone);

		/* purge (or whatever) the directory proper */
		if (!leftone)
		{
			*--newptr = '\0';
			ret = (*action)(newpath, NULL);
		}
		(void) closedir(d);
	}
	else if (S_ISREG(statbuf.st_mode))
	{
		char *end = pathname + strlen(pathname) - 1;
		char *start;
		char *scan;
		char host[MAXHOSTNAMELEN];
		char *hostptr = host;

		/*
		**  Reconstruct the host name from the path to the
		**  persistent information.
		*/

		do
		{
			if (hostptr != host)
				*(hostptr++) = '.';
			start = end;
			while (*(start - 1) != '/')
				start--;

			if (*end == '.')
				end--;

			for (scan = start; scan <= end; scan++)
				*(hostptr++) = *scan;

			end = start - 2;
		} while (*end == '.');

		*hostptr = '\0';

		/*
		**  Do something with the file containing the persistent
		**  information.
		*/
		ret = (*action)(pathname, host);
	}

	return ret;
}
/*
**  MCI_PRINT_PERSISTENT -- print persistent info
**
**	Dump the persistent information in the file 'pathname'
**
**	Parameters:
**		pathname -- the pathname to the status file.
**		hostname -- the corresponding host name.
**
**	Returns:
**		0
*/

int
mci_print_persistent(pathname, hostname)
	char *pathname;
	char *hostname;
{
	static int initflag = FALSE;
	FILE *fp;
	int width = Verbose ? 78 : 25;
	bool locked;
	MCI mcib;

	/* skip directories */
	if (hostname == NULL)
		return 0;

	if (!initflag)
	{
		initflag = TRUE;
		printf(" -------------- Hostname --------------- How long ago ---------Results---------\n");
	}

	fp = safefopen(pathname, O_RDWR, FileMode,
		       SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH);

	if (fp == NULL)
	{
		if (tTd(56, 1))
			dprintf("mci_print_persistent: cannot open %s: %s\n",
				pathname, errstring(errno));
		return 0;
	}

	FileName = pathname;
	memset(&mcib, '\0', sizeof mcib);
	if (mci_read_persistent(fp, &mcib) < 0)
	{
		syserr("%s: could not read status file", pathname);
		(void) fclose(fp);
		FileName = NULL;
		return 0;
	}

	locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
	(void) fclose(fp);
	FileName = NULL;

	printf("%c%-39s %12s ",
		locked ? '*' : ' ', hostname,
		pintvl(curtime() - mcib.mci_lastuse, TRUE));
	if (mcib.mci_rstatus != NULL)
		printf("%.*s\n", width, mcib.mci_rstatus);
	else if (mcib.mci_exitstat == EX_TEMPFAIL && mcib.mci_errno != 0)
		printf("Deferred: %.*s\n", width - 10, errstring(mcib.mci_errno));
	else if (mcib.mci_exitstat != 0)
	{
		int i = mcib.mci_exitstat - EX__BASE;
		extern int N_SysEx;
		extern char *SysExMsg[];

		if (i < 0 || i >= N_SysEx)
		{
			char buf[80];

			snprintf(buf, sizeof buf, "Unknown mailer error %d",
				mcib.mci_exitstat);
			printf("%.*s\n", width, buf);
		}
		else
			printf("%.*s\n", width, &(SysExMsg[i])[5]);
	}
	else if (mcib.mci_errno == 0)
		printf("OK\n");
	else
		printf("OK: %.*s\n", width - 4, errstring(mcib.mci_errno));

	return 0;
}
/*
**  MCI_PURGE_PERSISTENT -- Remove a persistence status file.
**
**	Parameters:
**		pathname -- path to the status file.
**		hostname -- name of host corresponding to that file.
**			NULL if this is a directory (domain).
**
**	Returns:
**		0 -- ok
**		1 -- file not deleted (too young, incorrect format)
**		< 0 -- some error occurred
*/

int
mci_purge_persistent(pathname, hostname)
	char *pathname;
	char *hostname;
{
	struct stat statbuf;
	char *end = pathname + strlen(pathname) - 1;
	int ret;

	if (tTd(56, 1))
		dprintf("mci_purge_persistent: purging %s\n", pathname);

	ret = stat(pathname, &statbuf);
	if (ret < 0)
	{
		if (tTd(56, 2))
			dprintf("mci_purge_persistent: Failed to stat %s: %s\n",
				pathname, errstring(errno));
		return ret;
	}
	if (curtime() - statbuf.st_mtime < MciInfoTimeout)
		return 1;
	if (hostname != NULL)
	{
		/* remove the file */
		if (unlink(pathname) < 0)
		{
			if (tTd(56, 2))
				dprintf("mci_purge_persistent: failed to unlink %s: %s\n",
					pathname, errstring(errno));
		}
	}
	else
	{
		/* remove the directory */
		if (*end != '.')
			return 1;

		if (tTd(56, 1))
			dprintf("mci_purge_persistent: dpurge %s\n", pathname);

		if (rmdir(pathname) < 0)
		{
			if (tTd(56, 2))
				dprintf("mci_purge_persistent: rmdir %s: %s\n",
					pathname, errstring(errno));
		}

	}

	return 0;
}
/*
**  MCI_GENERATE_PERSISTENT_PATH -- generate path from hostname
**
**	Given `host', convert from a.b.c to $QueueDir/.hoststat/c./b./a,
**	putting the result into `path'.  if `createflag' is set, intervening
**	directories will be created as needed.
**
**	Parameters:
**		host -- host name to convert from.
**		path -- place to store result.
**		pathlen -- length of path buffer.
**		createflag -- if set, create intervening directories as
**			needed.
**
**	Returns:
**		0 -- success
**		-1 -- failure
*/

static int
mci_generate_persistent_path(host, path, pathlen, createflag)
	const char *host;
	char *path;
	int pathlen;
	bool createflag;
{
	char *elem, *p, *x, ch;
	int ret = 0;
	int len;
	char t_host[MAXHOSTNAMELEN];
#if NETINET6
	struct in6_addr in6_addr;
#endif /* NETINET6 */

	/*
	**  Rationality check the arguments.
	*/

	if (host == NULL)
	{
		syserr("mci_generate_persistent_path: null host");
		return -1;
	}
	if (path == NULL)
	{
		syserr("mci_generate_persistent_path: null path");
		return -1;
	}

	if (tTd(56, 80))
		dprintf("mci_generate_persistent_path(%s): ", host);

	if (*host == '\0' || *host == '.')
		return -1;

	/* make certain this is not a bracketed host number */
	if (strlen(host) > sizeof t_host - 1)
		return -1;
	if (host[0] == '[')
		(void) strlcpy(t_host, host + 1, sizeof t_host);
	else
		(void) strlcpy(t_host, host, sizeof t_host);

	/*
	**  Delete any trailing dots from the hostname.
	**  Leave 'elem' pointing at the \0.
	*/

	elem = t_host + strlen(t_host);
	while (elem > t_host &&
	       (elem[-1] == '.' || (host[0] == '[' && elem[-1] == ']')))
		*--elem = '\0';

#if NETINET || NETINET6
	/* check for bogus bracketed address */
	if (host[0] == '[' &&
# if NETINET6
	    inet_pton(AF_INET6, t_host, &in6_addr) != 1 &&
# endif /* NETINET6 */
# if NETINET
	    inet_addr(t_host) == INADDR_NONE
# endif /* NETINET */
	    )
		return -1;
#endif /* NETINET || NETINET6 */

	/* check for what will be the final length of the path */
	len = strlen(HostStatDir) + 2;
	for (p = (char *) t_host; *p != '\0'; p++)
	{
		if (*p == '.')
			len++;
		len++;
		if (p[0] == '.' && p[1] == '.')
			return -1;
	}
	if (len > pathlen || len < 1)
		return -1;

	(void) strlcpy(path, HostStatDir, pathlen);
	p = path + strlen(path);

	while (elem > t_host)
	{
		if (!path_is_dir(path, createflag))
		{
			ret = -1;
			break;
		}
		elem--;
		while (elem >= t_host && *elem != '.')
			elem--;
		*p++ = '/';
		x = elem + 1;
		while ((ch = *x++) != '\0' && ch != '.')
		{
			if (isascii(ch) && isupper(ch))
				ch = tolower(ch);
			if (ch == '/')
				ch = ':';	/* / -> : */
			*p++ = ch;
		}
		if (elem >= t_host)
			*p++ = '.';
		*p = '\0';
	}

	if (tTd(56, 80))
	{
		if (ret < 0)
			dprintf("FAILURE %d\n", ret);
		else
			dprintf("SUCCESS %s\n", path);
	}

	return ret;
}

⌨️ 快捷键说明

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