Beispiel #1
0
/* Lookup a text. If it does not exist, create it. */
char *
grecs_install_text(const char *str)
{
	struct grecs_syment key;
	struct grecs_syment *ent;
	int install = 1;

	if (!text_table) {
		text_table = grecs_symtab_create_default(
			              sizeof(struct grecs_syment));
		if (!text_table)
			grecs_alloc_die();
	}
  
	key.name = (char*) str;
	ent = grecs_symtab_lookup_or_install(text_table, &key, &install);
	if (!ent)
		grecs_alloc_die();
	return ent->name;
}
Beispiel #2
0
static void
reset_point(struct grecs_locus_point *point, struct grecs_symtab *st)
{
	struct grecs_syment *ent, key;
	int install = 1;

	if (!point->file)
		return;
	key.name = (char*) point->file;
	ent = grecs_symtab_lookup_or_install(st, &key, &install);
	if (!ent)
		grecs_alloc_die();
	point->file = ent->name;
}
Beispiel #3
0
static int
parse_inet(struct grecs_sockaddr **ret,
	   int family, const char *arg, const char *addrstr,
	   struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus)
{
	int rc;
	struct addrinfo hints;
	struct addrinfo *res, *ap;
	const char *node = NULL;
	char *nodebuf = NULL;
	const char *service = NULL;
	struct grecs_sockaddr *head = NULL, *tail = NULL;
	char portbuf[64];

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = family;
	hints.ai_socktype = SOCK_STREAM;

	if ((family == AF_INET6 || family == AF_UNSPEC)
	    && addrstr[0] == '[') {
		char *p = strchr(addrstr + 1, ']');
		if (p && p > addrstr + 1) {
			size_t len;
			
			addrstr++;
			len = p - addrstr;
			nodebuf = grecs_malloc(len + 1);
			memcpy(nodebuf, addrstr, len);
			nodebuf[len] = 0;
			node = nodebuf;
			service = p + 1;
			family = AF_INET6;
		} else
			service = strchr(addrstr, ':');
	} else
		service = strrchr(addrstr, ':');

	if (service && *service) {
		if (*service != ':') {
			grecs_error(locus, 0,
				    _("%s: garbage near %s"), arg, service);
			return -1;
		}
		service++;
	}
	
	if (!node) {
		if (service) {
			size_t len = service - addrstr - 1;
			
			if (len == 0)
				node = NULL;
			else {
				nodebuf = grecs_malloc(len + 1);
				memcpy(nodebuf, addrstr, len);
				nodebuf[len] = 0;
				node = nodebuf;
			}
		} else {
			if (grecs_str_is_ipaddr(addrstr))
				node = addrstr;
			else if (grecs_str_is_num(addrstr)) {
				service = addrstr;
				hints.ai_flags |= AI_NUMERICSERV;
			}
		}
	}
	
	if (!service || !*service) {
		if (!node && addrstr[0])
			node = addrstr;
		if (gh->flags & GRECS_HINT_SERVICE) {
			service = gh->service;
		} else if (gh->flags & GRECS_HINT_PORT) {
			snprintf(portbuf, sizeof portbuf, "%hu", gh->port);
			service = portbuf;
			hints.ai_flags |= AI_NUMERICSERV;
		} else if (!(gh->flags & GRECS_AH_PASSIVE)) {
			grecs_error(locus, 0,
				    _("service not specified: %s"), arg);
			return -1;
		}
	}
	
	if (!node) {
		if (gh->flags & GRECS_AH_PASSIVE)
			hints.ai_flags |= AI_PASSIVE;
	}
	
	rc = getaddrinfo(node, service, &hints, &res);
	free(nodebuf);
	switch (rc) {
	case 0:
		break;
	case EAI_SYSTEM:
		grecs_error(locus, 0,
			    _("%s: cannot parse address: %s"),
			    arg, strerror(errno));
		break;
	case EAI_BADFLAGS:
	case EAI_SOCKTYPE:
		grecs_error(locus, 0,
			    "%s:%d: internal error converting %s",
			    __FILE__,__LINE__,arg);
		break;
	case EAI_MEMORY:
		grecs_alloc_die();
	default:
		grecs_error(locus, 0,
			    "%s: %s", arg, gai_strerror(rc));
		return -1;
	}

	for (ap = res; ap; ap = ap->ai_next) {
		if (family == AF_UNSPEC || ap->ai_addr->sa_family == family) {
			struct grecs_sockaddr *sp =
				grecs_sockaddr_new(ap->ai_addrlen);
			memcpy(sp->sa, ap->ai_addr, ap->ai_addrlen);
			sp->len = ap->ai_addrlen;
			if (!head)
				head = sp;
			else
				tail->next = sp;
			tail = sp;
		}
	}
	freeaddrinfo(res);
	*ret = head;
	return 0;
}