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

📄 savecopy.c

📁 UNIX网络编程第一卷第三版源代码 UNIX网络编程第一卷第三版源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			search[nsearch].host = hostname;			search[nsearch].family = AF_INET;			nsearch++;			break;#endif#ifdef	IPV6		case AF_INET6:			search[nsearch].host = hostname;			search[nsearch].family = AF_INET6;			nsearch++;			break;#endif		case AF_UNSPEC:#ifdef	IPV6			search[nsearch].host = hostname;			search[nsearch].family = AF_INET6;	/* IPv6 first */			nsearch++;#endif#ifdef	IPV4			search[nsearch].host = hostname;			search[nsearch].family = AF_INET;	/* then IPv4 */			nsearch++;#endif			break;		}	}	if (nsearch < 1 || nsearch > 2)		err_quit("nsearch = %d", nsearch);	return(nsearch);}/* * Create and fill in a addrinfo{}. */static intga_aistruct(struct addrinfo ***paipnext, const struct addrinfo *hintsp,			void *addr, int family){	struct addrinfo	*ai;	if ( (ai = calloc(1, sizeof(struct addrinfo))) == NULL)		return(EAI_MEMORY);	ai->ai_next = NULL;	ai->ai_canonname = NULL;	**paipnext = ai;	*paipnext = &ai->ai_next;	if ( (ai->ai_socktype = hintsp->ai_socktype) == 0)		ai->ai_flags |= AI_CLONE;	ai->ai_protocol = hintsp->ai_protocol;		switch ((ai->ai_family = family)) {#ifdef	IPV4		case AF_INET: {			struct sockaddr_in	*sinptr;				/* 4allocate sockaddr_in{} and fill in all but port */			if ( (sinptr = calloc(1, sizeof(struct sockaddr_in))) == NULL)				return(EAI_MEMORY);#ifdef	HAVE_SOCKADDR_SA_LEN			sinptr->sin_len = sizeof(struct sockaddr_in);#endif			sinptr->sin_family = AF_INET;			memcpy(&sinptr->sin_addr, addr, sizeof(struct in_addr));			ai->ai_addr = (struct sockaddr *) sinptr;			ai->ai_addrlen = sizeof(struct sockaddr_in);			break;		}#endif	/* IPV4 */	#ifdef	IPV6				/* 4allocate sockaddr_in6{} and fill in all but port */		case AF_INET6: {			struct sockaddr_in6	*sin6ptr;			if ( (sin6ptr = calloc(1, sizeof(struct sockaddr_in6))) == NULL)				return(EAI_MEMORY);#ifdef	HAVE_SOCKADDR_SA_LEN			sin6ptr->sin6_len = sizeof(struct sockaddr_in6);#endif			sin6ptr->sin6_family = AF_INET6;			memcpy(&sin6ptr->sin6_addr, addr, sizeof(struct in6_addr));			ai->ai_addr = (struct sockaddr *) sin6ptr;			ai->ai_addrlen = sizeof(struct sockaddr_in6);			break;		}#endif	/* IPV6 */	}	return(0);}/* * This function handles the service string. */static intga_serv(struct addrinfo *aihead, const struct addrinfo *hintsp,		const char *serv){	int				port, rc, nfound;	struct servent	*sptr;		/* 4check for port number first */	if (isdigit(serv[0]) && hintsp->ai_socktype != 0) {		port = htons(atoi(serv));		if ( (rc = ga_port(aihead, port, hintsp->ai_socktype)) == 0)			return(EAI_NONAME);		else if (rc < 0)			return(EAI_MEMORY);		else			return(0);	}		/* 4try TCP first */	nfound = 0;	if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_STREAM) {		if ( (sptr = getservbyname(serv, "tcp")) != NULL) {			if ( (rc = ga_port(aihead, sptr->s_port, SOCK_STREAM)) < 0)				return(EAI_MEMORY);			nfound += rc;		}	}		/* 4try UDP */	if (hintsp->ai_socktype == 0 || hintsp->ai_socktype == SOCK_DGRAM) {		if ( (sptr = getservbyname(serv, "udp")) != NULL) {			if ( (rc = ga_port(aihead, sptr->s_port, SOCK_DGRAM)) < 0)				return(EAI_MEMORY);			nfound += rc;		}	}	if (nfound == 0) {		if (hintsp->ai_socktype == 0)			return(EAI_NONAME);	/* all calls to getservbyname() failed */		else			return(EAI_SERVICE);/* service not supported for socket type */	}	return(0);}/* * Go through all the addrinfo structures, checking for a match of the * socket type and filling in the socket type, and then the port number * in the corresponding socket address structures. * * The AI_CLONE flag works as follows.  Consider a multihomed host with * two IP addresses and no socket type specified by the caller.  After * the "host" search there are two addrinfo structures, one per IP address. * Assuming a service supported by both TCP and UDP (say the daytime * service) we need to return *four* addrinfo structures: *		IP#1, SOCK_STREAM, TCP port, *		IP#1, SOCK_DGRAM, UDP port, *		IP#2, SOCK_STREAM, TCP port, *		IP#2, SOCK_DGRAM, UDP port. * To do this, when the "host" loop creates an addrinfo structure, if the * caller has not specified a socket type (hintsp->ai_socktype == 0), the * AI_CLONE flag is set.  When the following function finds an entry like * this it is handled as follows: If the entry's ai_socktype is still 0, * this is the first use of the structure, and the ai_socktype field is set. * But, if the entry's ai_socktype is nonzero, then we clone a new addrinfo * structure and set it's ai_socktype to the new value.  Although we only * need two socket types today (SOCK_STREAM and SOCK_DGRAM) this algorithm * will handle any number.  Also notice that Posix.1g requires all socket * types to be nonzero. */static intga_port(struct addrinfo *aihead, int port, int socktype)		/* port must be in network byte order */{	int				nfound = 0;	struct addrinfo	*ai;	for (ai = aihead; ai != NULL; ai = ai->ai_next) {		if (ai->ai_flags & AI_CLONE) {			if (ai->ai_socktype != 0) {				if ( (ai = ga_clone(ai)) == NULL)					return(-1);		/* memory allocation error */				/* ai points to newly cloned entry, which is what we want */			}		} else if (ai->ai_socktype != socktype)			continue;		/* ignore if mismatch on socket type */		ai->ai_socktype = socktype;		switch (ai->ai_family) {#ifdef	IPV4			case AF_INET:				((struct sockaddr_in *) ai->ai_addr)->sin_port = port;				nfound++;				break;#endif#ifdef	IPV6			case AF_INET6:				((struct sockaddr_in6 *) ai->ai_addr)->sin6_port = port;				nfound++;				break;#endif		}	}	return(nfound);}/* * Clone a new addrinfo structure from an existing one. */static struct addrinfo *ga_clone(struct addrinfo *ai){	struct addrinfo	*new;	if ( (new = calloc(1, sizeof(struct addrinfo))) == NULL)		return(NULL);	new->ai_next = ai->ai_next;	ai->ai_next = new;	new->ai_flags = 0;				/* make sure AI_CLONE is off */	new->ai_family = ai->ai_family;	new->ai_socktype = ai->ai_socktype;	new->ai_protocol = ai->ai_protocol;	new->ai_canonname = NULL;	new->ai_addrlen = ai->ai_addrlen;	if ( (new->ai_addr = malloc(ai->ai_addrlen)) == NULL)		return(NULL);	memcpy(new->ai_addr, ai->ai_addr, ai->ai_addrlen);	return(new);}#ifdef	UNIXDOMAIN/* * Do everything for a Unix domain socket. * Only one addrinfo{} is returned. */static intga_unix(const char *path, struct addrinfo *hintsp, struct addrinfo **result){	struct addrinfo		*ai;	struct sockaddr_un	*unp;	if (hintsp->ai_socktype == 0)		return(EAI_SOCKTYPE);	/* we cannot tell socket type from service */	if ( (ai = calloc(1, sizeof(struct addrinfo))) == NULL)		return(NULL);	ai->ai_flags = 0;	ai->ai_family = AF_LOCAL;	ai->ai_socktype = hintsp->ai_socktype;	ai->ai_protocol = 0;		/* allocate and fill in a socket address structure */	ai->ai_addrlen = sizeof(struct sockaddr_un);	if ( (ai->ai_addr = malloc(ai->ai_addrlen)) == NULL)		return(EAI_MEMORY);	unp = (struct sockaddr_un *) ai->ai_addr;	unp->sun_family = AF_UNIX;	strncpy(unp->sun_path, path, sizeof(unp->sun_path));	ai->ai_canonname = NULL;	/* maybe return the i-node number :-) */	ai->ai_next = NULL;	*result = ai;	if (hintsp->ai_flags & AI_PASSIVE)		unlink(path);		/* OK if this fails */	return(0);		/* success */}#endif	/* UNIXDOMAIN */voidfreeaddrinfo(struct addrinfo *aihead){	struct addrinfo	*ai, *ainext;	for (ai = aihead; ai != NULL; ai = ainext) {		if (ai->ai_addr != NULL)			free(ai->ai_addr);		/* the socket address structure */		if (ai->ai_canonname != NULL)			free(ai->ai_canonname);	/* the canonical name */		ainext = ai->ai_next;		/* can't fetch ai_next after free() */		free(ai);					/* the addrinfo{} itself */	}}

⌨️ 快捷键说明

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